Wednesday, December 28, 2011

Slow UPDATE


По поводу вчерашнего медленного UPDATE.

Мы запускаем UPDATE над идентичными данными на двух серверах - Oracle Database Appliance (ODA) и старенький сервер. В табличке ровно 10 млн строк. Выражение, которое мы тестируем предельно простое:

UPDATE TAB1
SET COL1 = COL1
, COL2 = COL2
, COL3 = COL3
, COL4 = COL4

Старенький сервер это 4-ядерный XEON 2.66 cache 4m , RAM 4g (533MHz).
ODA это два 6-ядерных Xeon 3.06 cache 12M, RAM 96g (1333MHz).
При этом старенький сервер опережает ОДУ со счетом 13 минут против 21.

Базы в обоих случаях 11.2.0.2. Никакого шифрования ТП нет.
Вся табличка находится в SGA, физические чтения из датафайлов отсутствуют.
Всяческие ожидания также отсутствуют. В обоих случаях 95% сессия проводит на ЦПУ.

Вот такая картина на ODA:

Top 5 Timed Foreground Events

EventWaitsTime(s)Avg wait (ms)% DB timeWait Class
DB CPU
1,360
95.19
gc current grant 2-way90,2943802.69Cluster
gc current block 2-way67,0513612.54Cluster
reliable message6,016510.35Other
gc cr multi block request1,085430.26Cluster


Поскольку ожидания отсутсвуют как класс, то для выяснения чем занмается процесс на ЦПУ сделали несколько снимков pstack-ом на старом и новом серверах. Слева ODA, справа - старый сервер:
#0  0x000000000909080d in kdr4chk ()      
#1  0x000000000908b9ce in kdb4chk1 ()     
#2  0x000000000908a493 in kd4chk ()       
#3  0x0000000008f55266 in kdgchk ()       
#4  0x0000000008dd7b0b in ktbdbchk ()     
#5  0x0000000008ded010 in kcbchk_ctx ()   
#6  0x0000000008f8fc93 in kco_blkchk ()   
#7  0x0000000008f8e989 in kcoapl ()       
#8  0x0000000008e0d8ab in kcbapl ()       
#9  0x0000000008f95c4e in kcrfw_redo_gen ()
                                                                  
                                                                                                             
#10 0x0000000000e4540c in kcbchg1_main ()       #0  0x0021f7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#11 0x0000000008e0dbfb in kcbchg1 ()            #1  0x002c7342 in times () from /lib/tls/libc.so.6           
#12 0x0000000008dcc876 in ktuchg2 ()            #2  0x0fcc9754 in sltrgatime64 ()                            
#13 0x0000000008dd7093 in ktbchg2 ()            #3  0x0fac31b5 in kcbchg1_main ()                            
#14 0x0000000008d8afef in kddchg ()             #4  0x0fac206b in kcbchg1 ()                                 
#15 0x000000000488ed65 in kdblccovwr ()         #5  0x0fa94300 in ktuchg2 ()                                 
#16 0x00000000048908e8 in kdblcovw ()           #6  0x0fa9d60a in ktbchg2 ()                                 
#17 0x0000000008d82d52 in kduurp ()             #7  0x0fa56b58 in kddchg ()                                  
#18 0x0000000008d7fb66 in kdusru ()             #8  0x087c65db in kddlok ()                                  
#19 0x0000000008d78c14 in kauupd ()             #9  0x087c4cad in kddlkr ()                                  
#20 0x0000000008f3f7f6 in updrow ()             #10 0x0fc02392 in updrow ()                                  
#21 0x00000000023cd72c in qerupFetch ()         #11 0x09d19442 in qerupFetch ()                              
#22 0x0000000001e989ee in updaul ()             #12 0x09830eaa in updaul ()                                  
#23 0x0000000001e9686e in updThreePhaseExe ()   #13 0x0982f56f in updThreePhaseExe ()                        
#24 0x0000000001e9616d in updexe ()             #14 0x0982e85a in updexe ()                                  
#25 0x0000000008ed2a96 in opiexe ()             #15 0x0fb80330 in opiexe ()                                  
#26 0x0000000001b1816b in kpoal8 ()             #16 0x09517c5d in kpoal8 ()                                  
#27 0x000000000172dded in opiodr ()             #17 0x0fb7afb7 in opiodr ()                                  
#28 0x00000000090600b1 in ttcpip ()             #18 0x0fcf013e in ttcpip ()                                  
#29 0x000000000171c86e in opitsk ()             #19 0x091cdb0e in opitsk ()                                  
#30 0x000000000172150e in opiino ()             #20 0x091d17d7 in opiino ()                                  
#31 0x000000000172dded in opiodr ()             #21 0x0fb7afb7 in opiodr ()                                  
#32 0x00000000017187c4 in opidrv ()             #22 0x091c9fbb in opidrv ()                                  
#33 0x0000000001d8fa77 in sou2o ()              #23 0x09747df4 in sou2o ()                                   
#34 0x0000000000a07d05 in opimai_real ()        #24 0x0854f0a3 in opimai_real ()                             
#35 0x0000000001d94f20 in ssthrdmain ()         #25 0x0974cdce in ssthrdmain ()                              
#36 0x0000000000a07c71 in main ()               #26 0x0854f01f in main ()                                    

Pstack - показывает OPI-вызовы снизу вверх. Т.е. нижняя строка - это заголовок программы, функция main().

Из сравнения стала видна разница:

#0  0x000000000909080d in kdr4chk ()       
#1  0x000000000908b9ce in kdb4chk1 ()      
#2  0x000000000908a493 in kd4chk ()        
#3  0x0000000008f55266 in kdgchk ()        
#4  0x0000000008dd7b0b in ktbdbchk ()      
#5  0x0000000008ded010 in kcbchk_ctx ()    
#6  0x0000000008f8fc93 in kco_blkchk ()    
#7  0x0000000008f8e989 in kcoapl ()        
#8  0x0000000008e0d8ab in kcbapl ()        
#9  0x0000000008f95c4e in kcrfw_redo_gen ()


А точнее, набор функций:

kdr4chk  
kdb4chk1
kd4chk
kdgchk
ktbdbchk
kcbchk_ctx 
kco_blkchk   

В имени каждой функции заметны буковки chk = CHECK.

Поэтому следующим шагом на обоих инстансах была выполнена команда:

На старом сервере:
SQL> show parameter db_block_check

NAME                                 TYPE        VALUE
------------------------------------ ----------- -------
db_block_checking                    string      FALSE
db_block_checksum                    string      TYPICAL

А в инит файле БД на ODA стоит:

db_block_checksum    = "FULL"
db_block_checking      = "FULL"

Отключаем эти настройки - побеждает ОДА со счетом 8 мин против 13:

 

Резюме:
- На ODA БД по-умолчанию создается с чрезвычайно затратными настройками. Отключение их позволяет значительно повысить скорость транзакций. Лицензия на ODA не запрещает пользователю создать свою БД со своими настройками.
-  Применение настроек
db_block_checksum    = "FULL"
db_block_checking      = "FULL"
 замедляет транзакции в 3-4 раза.
- команда pstack является мощным инструментом для исследования производительности в тех случаях, когда процесс все делает на ЦПУ, но непонятно, чем он там реально занимается. Курс Оракла по Performance Tuning в данном случае вам ничем помочь не сможет.

Does DEALLOCATE UNUSED or SHRINK SPACE will free space occupied by LOB segment?

Lets check how it works. My env is DB 19.20@Linux-x64 1) I created the table with 4 LOB columns of 4 different LOB types: BASICFILE BLOB, BA...