Randolph Geistã¯ãOracleããŒã¿ããŒã¹ã®ããã©ãŒãã³ã¹ã«é¢é£ãããšã©ãŒã®ä¿®æ£ãå°éãšããŠããŸãã 圌ã¯ãSQLã³ãŒãå®è¡ããã³Oracleæé©åãã¯ãããžãŒã®åæã®åéã§ãäžçæé«ã®å°é家ã®äžäººã§ãã 圌ã¯ãOracle Database AdministratorïŒOCP DBAïŒããŒãžã§ã³8iã9iãããã³10gã®èªå®ãåããŠããŸãã
Oracle Advanced Troubleshooting Session-PGA / UGAã¡ã¢ãªã®æçå
ã¯ã©ã€ã¢ã³ãã®ããŒã¿ããŒã¹ã®èšºæããã³ãã©ãã«ã·ã¥ãŒãã£ã³ã°ã»ãã·ã§ã³ã¯ãåé¡ã®æ¬¡ã®èª¬æããå§ãŸããŸãããç¹å®ã®ç°å¢ã§ã¯ãåå¥ã®ãããããã»ã¹ã«äºæ³ãããã¯ããã«é·ãæéããããå ŽåããããŸãïŒæ°åãæ°æéã§ã¯ãªãïŒã ããã«ãç£èŠäžã«ãéæšæºã®åäœãããSQLã¯ãšãªãæ€åºã§ããŸãã
ãã®ããããŸã第äžã«ãåé¡ãåçŸããæ¹æ³ãåŠã¶å¿ èŠããããŸããã
ããã«ãä»ã®å€ãã®ã¹ãã¢ãããã·ãŒãžã£/ããã±ãŒãžã«ã¢ã¯ã»ã¹ããXMLããŒã¿ãå«ãLOBïŒã©ãŒãžãªããžã§ã¯ãïŒãåŠçããããã±ãŒãžãããè€éãªPL / SQLã¹ãã¢ãããã·ãŒãžã£ãžã®ç¹å®ã®åŒã³åºããæ€åºããããšãã§ããŸããã
æåã«å ±åãããããã«ããã®ã¹ãã¢ãããã·ãŒãžã£ãã«ãŒãã§è€æ°ååŒã³åºããããã«ããŸããŸãªããŒã¿ããŒã¹ç°å¢ã§åé¡ãåçŸã§ããããšãå€æããŸããã
ãã®ã¹ãã¢ãããã·ãŒãžã£ã®åºæã®ããããã£ã¯ããæä»çãã¢ãŒãã§å®è¡ãããããšã§ãã ããã¯ãä»ã®ã¢ã¯ãã£ããªããžãã¹ããã»ã¹ãåæã«è¡ããã«ãååã«å€§ããIBMpSeriesãµãŒããŒïŒAIX 5.3ã11.1.0.7ã240 GB RAMãå€æ°ã®P6ãã«ãã³ã¢ããã»ããµãŒãé«äŸ¡ãªã¹ãã¬ãŒãžïŒã§å®è¡ãããããšãæå³ããŸãã åºæ¬çã«ã¯é 次å®è¡ã§ããã ç£èŠã®çµæããã®æé ã§ã¯2ã€ã®åçŽã§æ確ãªSQLã¯ãšãªã«ã»ãšãã©ã®æéãè²»ããããŸããã ãããã¯ãäžæã®ã€ã³ããã¯ã¹ãšROWIDã«ãã£ãŠåãå°ããªããŒãã«ã«ã¢ã¯ã»ã¹ããPL / SQLããåŒã³åºãããéçSQLã¯ãšãªã§ããã ãããã£ãŠã2ã€ã®SQLã¯ãšãªããããŸãããéåžžã®æ¡ä»¶äžã§ã¯ãææªã®å Žåãã€ã³ããã¯ã¹ãšããŒãã«ãå®å šã«ãããã¡ãã£ãã·ã¥ã«é 眮ãããããã2ã€ã®è«çèªã¿åããå¿ èŠã«ãªããŸãã
åè¿°ã®ãµã€ã¯ã«ã®éå§æã«ãããã®SQLã¯ãšãªã®å®è¡ãç£èŠãããšãåéå§æã«ïŒLOBXMLã®å 容ã«å¿ããŠïŒäœååãåŒã³åºãããããšãæããã«ãªããŸããã
ãããã¯éçSQLã§ãããããPL / SQLã«ãŒãœã«ãã£ãã·ã¥ïŒããã³ããŒã¿ãããã¯ãã£ãã·ã¥ïŒã¯éåžžã«ããŸãæ©èœããŸãã-ã€ãŸããã¯ãšãªã¯1åã ã解æããããã®åŸãç©çèªã¿åãã§ã¯ãªãè«çèªã¿åãã®ã¿ãå®è¡ããããã³ã«çºçããŸããã
ããã«ãã»ãšãã©ã®å Žåããããã®SQLã¯ãšãªã¯å°ããªããŒãã«ã§ç®çã®å€ãèŠã€ããããŸããã§ããã ããã¯ãå¹³åããŠã1ã€ã®ã¯ãšãªã®å®è¡ã«åäžã®è«çèªã¿åããå¿ èŠã§ããããšãæå³ããŸããã€ãŸããç®çã®å€ãå«ãŸããŠããªããããäžæã®ã€ã³ããã¯ã¹ã®ã¹ãã£ã³ã§ãã
ããŸããŸãªç°å¢ïŒAIXã®ä»£ããã«LinuxïŒã§ã®SQLã¯ãšãªå®è¡ã®çµ±èšã確èªãããšãåãSQLã¯ãšãªãåãåæ°å®è¡ãããŠããããšãããããŸãããããããã®ç°å¢ã§ã¯ããããžã§ãã®å®è¡ã«ãããæéãçããªããŸããã ãã®ç¹ã§ãèšå€§ãªæ°ã®SQLå®è¡ãå¥åŠã«èŠããŸãããããããã¯åé¡ã®äž»ãªåå ã§ã¯ãããŸããã§ããã
ã ããïŒ
â¢åé¡ã®åå ãšããŠXMLãè¡šãLOBã§åäœããã¹ãã¢ãããã·ãŒãžã£ãå®çŸ©ããŸããã
â¢ããã·ãŒãžã£æéã®ã»ãšãã©ã¯ãã¹ãã¢ãããã·ãŒãžã£ãéå§ããããã³ã«æ°ååå®è¡ããã2ã€ã®éçSQLã¯ãšãªã«è²»ããããŸããã
â¢ãã ãããããã®SQLã¯ãæé©ãªãå®è¡ãã©ã³ã䜿çšããå®éã«ã¯äžåºŠã«1ã€ã®è«çI / Oã®ã¿ãçæããŸããã
â¢ããããžã§ãã®ãæä»çãªãåäœã®ãããä»ã®ããã»ã¹ãšã®ç«¶åã¯äžå¯èœã§ããã
â¢èšãæããã°ããéå¹ççãªã¯ãšãªãã©ã³ããããªãœãŒã¹ã®ç«¶åãããã·ãªã¢ã«åããªã©ã®éåžžã®çãã«ã€ããŠè©±ããŠããããã§ã¯ãããŸããã
â¢ãããã£ãŠãããã©ãŒãã³ã¹ãç£èŠããéåžžã®æ¹æ³ïŒåŸ æ©ã€ãã³ããæ¡åŒµSQLãã¬ãŒã¹ãã¢ã¯ãã£ãã»ãã·ã§ã³ã®å±¥æŽãã»ãã·ã§ã³çµ±èš/ã·ã¹ãã çµ±èšãASH / AWR / ADDMã¬ããŒãã¯ãåé¡ã®æãããªåå ãæããã«ããŸããã§ããã
â¢å¥ã®ããã»ã¹ã§å®çŸ©ãããSQLã¯ãšãªãå®è¡ãããšãå®è¡ããšã«å¹³å10ãã€ã¯ãç§ïŒïŒïŒããããããšã瀺ãããŸãããããã¯éåžžã«é«éã§ãã ããã«é¢é£ããŠãåé¡ãçºçããŸãããããã®èŠæ±ãåé¡ãšããŠè¡šç€ºãããããã«ãªã£ãã®ã¯ã©ãããŠã§ãããåçŽãªãµã€ã¯ã«ã§èµ·åãããšã1ç§ã§1äžåã®èµ·åãå¯èœã§ãã
ãåŸ æ©ã€ãã³ãã¯äœã説æããªãããšãããïŒæã ïŒããšããå€å žçãªç¶æ³ã«çŽé¢ããŠããŸãã ç§ãã¡ãèŠããã¹ãŠ-ã»ãšãã©ã®æéã¯ãããã®SQLã®å®è¡ã«è²»ããããŸããã ç§ãã¡ãèŠã€ãããã¹ãŠ-ãããã¯ãã¹ãŠããããã®èŠæ±ãå®è¡ããåäžã®ããã»ããµã§çºçããŸããã
ãã ããã»ãã·ã§ã³ã®çµ±èšãã«ã¿ãç£èŠããŠããéïŒããšãã°ãTanel Poederã®ãsnapperããŠãŒãã£ãªãã£ã䜿çšããŠïŒãèå³æ·±ãç¹ãçºèŠãããŸãããããã»ã¹äžãããã»ã¹ã¯ããå€ãã®PGA / UGAã¡ã¢ãªãå¿ èŠãšããŸããã
ãããã£ãŠãé«åºŠãªåé¡è§£æ±ºæ¹æ³ãé©çšããæãæ¥ãŸãããããšãã°ãOak Tableã®åå è ã§ããTanel Poderã¯ããã®åéã§å€ãã®ç 究ãè¡ããå€æ°ã®æçšãªããŒã«ãæäŸããŸããã
ãããªããã§ãã¯ã®éçšã§ãããã«ã©ã®æ¹åã«é²ãã¹ããã決å®ããããã€ãã®ç°åžžãçºèŠãããŸããã
PGA / UGAããã»ã¹ã®æ¶è²»ã¯ãPL / SQLã¹ãã¢ãããã·ãŒãžã£ãéå§ããã«ãŒãã®å埩ããšã«å¢å ããŸããã ã©ããã«ã¡ã¢ãªã®åé¡ããããŸããã ãã®ç¹ã§ãPGA / UGAããã»ã¹ã®ã¡ã¢ãªãã³ãã確èªããããšããå§ãããŸãã
泚æïŒã¡ã¢ãªãã³ããååŸãããšãã·ã¹ãã ãŸãã¯ããã»ã¹ãç Žæããå¯èœæ§ããããããå®çšŒåç°å¢ã§ãã®æäœãå®è¡ãããšãã¯ååã«æ³šæããŠãã ããã PGAã¡ã¢ãªãã³ãã®ååŸã¯éåžž1ã€ã®ããã»ã¹ã«ã®ã¿åœ±é¿ãããããããŸãéèŠã§ã¯ãããŸããïŒãã¡ãããããã¯ã°ã©ãŠã³ãããã»ã¹ã§ãªãéãïŒã
EVENTSã䜿çšããŠã¡ã¢ãªãã³ããååŸã§ããŸãã
ALTER SESSION SET EVENTS 'immediate trace name heapdumplevel <lvl>';
SETOSPIDãSETORAPIDããŸãã¯SETMYPIDã䜿çšããŠããã»ã¹ãå®çŸ©ããåŸãORADEBUG ASSYSDBAã䜿çšããŠã¡ã¢ãªãã³ããèŠæ±ããããšãã§ããŸãã
ORADEBUG DUMP HEAPDUMP <LVL>';
䜿çšå¯èœãªã¡ã¢ãªãã³ãã®ã¬ãã«ã®æŠèŠã«ã€ããŠã¯ãJulian Dykeã®Webãµã€ããåç §ããŠãã ããã
ãã®å Žåã5çªç®ã®ã¬ãã«ïŒ5 = 4 + 1ãã€ãŸãPGAãšUGAïŒã®ãã³ãã§ååãªããã§ãïŒçŸåšã®ãŠãŒã¶ãŒã³ãŒã«ã«èå³ãããå Žåã¯ãã¬ãã«29 = 8 + 16 + 4 + 1ãå¿ èŠã§ãïŒã
Oracleã®æžç±Oak Table Expert Adviceã®ç¬¬8ç« ã§ã Charlesãšç§ã¯ããã®å Žåã«äœ¿çšãããæãéèŠãªã¡ã¢ãªãã³ããªãã·ã§ã³ãšãã®ä»ã®ããã©ãŒãã³ã¹ç£èŠæ¹æ³ã«ã€ããŠèª¬æããŠããŸãã
çµæã®ãã¬ãŒã¹ãã¡ã€ã«ã¯ãããšãã°ã Tanela heapdump_analyzerã¹ã¯ãªããã䜿çšããŠæåã«åæã§ããŸãããã®å Žåããã¬ãŒã¹ãã¡ã€ã«ã®ããªã¥ãŒã ã¯éåžžã«å€§ããããã heapdump_analyzerããawkãå°ãä¿®æ£ããããŒãžã§ã³ã䜿çšããŠãå€éšOracleããŒãã«ãšããŠæ¥ç¶ããããã¡ã€ã«ãäœæããŸãããã®ããŒã¿ã«å¯ŸããŠããè€éãªã¯ãšãªãå®è¡ããããšãã§ããŸããã
ãã¬ãŒã¹ãã¡ã€ã«ãå€éšOracleããŒãã«ãšããŠäœ¿çšããã®ã«é©ãããã¡ã€ã«ã«å€æããã³ãã³ãã次ã«ç€ºããŸãã
cat $TRACE_FILE | awk ' /^HEAP DUMP heap name=/ { split($0,ht,"\""); HTYPE=ht[2]; doPrintOut = 1; } /Chunk/{ if ( doPrintOut == 1 ) { split($0,sf,"\""); printf "%10d , %16s, %16s, %16s\n", $4, HTYPE, $5, sf[2]; } } /Total heap size/ { doPrintOut=0; } ' > $EXT_TAB_DIR/heapdump.txt
以äžã¯ããã®ãããªå€éšããŒãã«ã®DDLã®äŸã§ãã
create table heapdump ( chunk_size integer , heap_type varchar2(16) , chunk_type varchar2(16) , alloc_reason varchar2(16) ) organization external ( type oracle_loader default directory ext_tab_dir access parameters ( records delimited by newline fields terminated by ',' lrtrim ) location ('heapdump.txt') );
ãã®ããã»ã¹ã¯äžæLOBã®ããªãŒã¯ããåŒãèµ·ãããŸã-LOBã®æ°ã®äžå®ã®å¢å ãV $ TEMPORARY_LOBSã§èŠ³å¯ãããŸãããããã¯é ãïŒã¹ãã¢ãããã·ãŒãžã£ãéå§ããããã³ã«1ã€ã®ãªããžã§ã¯ãïŒãäžæããŒãã«ã¹ããŒã¹ã®ã¡ã¢ãªæ¶è²»ã¯äœããŸãŸã§ãã
äœåºŠãç¹°ãè¿ããã2ã€ã®SQLã¯ãšãªã®å¹³åå®è¡æéãèšç®ãããšãæåã¯åå¥ã®å®è¡ãšåããããéãå®éã«å®è¡ãããããå®è¡ãåŸã ã«é ããªãããšãæããã«ãªããŸããã
æ°ååŸããããã®èŠæ±ã¯æåã¯æ°ãã€ã¯ãç§ããããŸããããæ°ããªç§ïŒïŒïŒããããŸããã åœç¶ã®ããšãªããããããã®èŠæ±ãå®äºããã®ã«äœåºŠãããã£ããããããããžã§ãã«ã¯æ°æéããããŸããã ããããä»ã§ã¯ãåå®è¡ã¯ããã»ã¹ã®æåãã1000åã®æéãããããŸããã
ãã調ã¹ãŠã¿ããšããã®ãããªã¹ããŒããŠã³ã¯å®è¡ããããã¹ãŠã®SQLã¯ãšãªã«åœ±é¿ããããšãæããã«ãªããŸããã ãããããããã®ã¯ãšãªã®å€ãã®å®è¡ã«ã¯ãããã«ããæ°ããªç§ããããæ°åå®è¡ããããããæ°ããªç§ã®å®è¡æéã®å¢å ã¯å®éã«ã¯ããã»ã©éèŠã§ã¯ãããŸããã§ããã ãããã¯éåžžã«é »ç¹ã«å®è¡ããããªã¯ãšã¹ãã§ãããå®è¡æéã®æ倧ã®ãå¢å ããåãåããŸããã
ãã®çµæãPL / SQLã¹ãã¢ãããã·ãŒãžã£ãéå§ãããµã€ã¯ã«ã®å®äºåŸããã®ã»ãã·ã§ã³å ã®ãã¹ãŠã®ããã»ã¹ã圱é¿ãåããããšãæããã«ãªããŸããã ããšãã°ãåçŽãªSELECT * FROMDUALæäœãŸãã¯PL / SQL nullãããã¯ïŒBEGINNULL; ENDïŒãå®è¡ããã«ã¯ãçŽ30åã®1ç§ïŒ0.3ç§ïŒïŒããããŸããã ïŒå¥ã®ã»ãã·ã§ã³ããŸã éããŠããéã«ïŒæ°ããã»ãã·ã§ã³ã§åãæäœãå³åº§ã«å®è¡ãããŸããïŒ0.01ç§æªæºã§ãSQL * Plusã¿ã€ã ã«ãŠã³ã¿ãŒã䜿çšããŠããŒã¿ãååŸãããŸããïŒ-ããã¯ãã®ã»ãã·ã§ã³ã§ã®ã¿å žåçã§ãããå šäœãšããŠã§ã¯ãããŸããã
ãããã£ãŠãæããã«ããå€ãã®CPUæéãå¿ èŠãšããäœããçŸããŸããã ããã«ããããåãæäœã®å®è¡æéãããããäœã§ãããã«é¢ä¿ãªãå¢å ããŸããã
ããã»ã¹ãå®äºããã®ã«æãæéãããããã®ãç解ããããã«ãããæ·±ãã¬ãã«ã«é²ã¿ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã¬ãã«ã§ãã¬ãŒã¹ã調ã¹ãŸãã æ®å¿µãªãããAIX 5.3ãæ±ã£ãŠãããããå¿ èŠãªæž¬å®ãè¡ãããã®ããŒã«ã®ã»ããã¯éåžžã«éãããŠããã AIXã¯DTraceããµããŒãããŠããŸãããæ°ããProbeVueããŒã«ã¯ãAIX 6以éã®ããŒãžã§ã³ã§ã®ã¿äœ¿çšã§ããŸãã ãããã£ãŠãOracleã®çµã¿èŸŒã¿oradebugshort_stackãšAIXã®procstackã®ã¿ãããããã©ã¢ã°ã©ãŠã³ãããã»ã¹ã®åŒã³åºãã¹ã¿ãã¯ãããµã³ãã«ãååŸããããã«äœ¿çšããŠããŸããã
ããããåã³ãã¿ãã«ã¯æå©ã«æ¥ãŸãã 圌ã®OStackProfããŒã«ãããã䜿çšããŠãã³ãŒã«ã¹ã¿ãã¯ããé ç®ãååŸã§ããŸããããããã»ã¹ãã¡ã¢ãªã®ç®¡çã«ã»ãšãã©ã®æéãè²»ãããããšãããããŸããã ã³ãŒã«ã¹ã¿ãã¯ã®é¢æ°åãå®éã«äœãæå³ããã®ã誰ãèšããªãã£ããããããã¯åãªãä»®å®ã§ããã MOS 175982.1ã®ããã¥ã¡ã³ãã«åºã¥ããŠãããã¯ãã¹ãŠADTã¡ã¢ãªç®¡çïŒOracleãªããžã§ã¯ãïŒã«é¢é£ããŠããŸããã
ã¹ã¿ãã¯ãã¬ãŒã¹ã¯æ¬¡ã®ããã«ãªããŸããã
Belowisthestackprefixcommontoallsamples: ------------------------------------------------------------------------ Frame->function() ------------------------------------------------------------------------ # 36 ->main() # 35 ->opimai_real()b0 # 34 ->sou2o() # 33 ->opidrv() # 32 ->opiodr()b98 # 31 ->opiino()f0 # 30 ->opitsk() # 29 ->ttcpip()c # 28 ->opiodr()b98 # 27 ->kpoal8()c # 26 ->opiexe() # 25 ->kkxexe()c # 24 ->peicnt() # 23 ->plsql_run() # 22 ->pfrrun() # 21 ->pfrrun_no_tool()c # 20 ->pfrinstr_EXECC()c # 19 ->pevm_EXECC()e4 # 18 ->psdnal()c # 17 ->psddr0() # 16 ->rpidrv() # ...(seecallprofilebelow) # # -#-------------------------------------------------------------------- # - Num.Samples ->incallstack() # ---------------------------------------------------------------------- 76 ->rpiswu2()c0->rpidru()->skgmstack()c4->rpidrus()c8->opiodr()b98->opipls()->opiexe()e4->auddft()b8->audbeg()->ktcxbr0()a0->kocbeg()->koctxbg()->kohalc()->kohalmc()->kghfru()c->44c0->-> 20 ->rpiswu2()c0->rpidru()->skgmstack()c4->rpidrus()c8->opiodr()b98->opipls()->opiexe()->44c0->-> 1 ->rpiswu2()c0->rpidru()->skgmstack()c4->rpidrus()c8->opiodr()b98->opipls()->opiexe()b8c->kksfbc()ec->ktcsna()c->ktucloGetGlobalMinScn()->44c0->-> 1 ->rpiswu2()c0->rpidru()->skgmstack()c4->rpidrus()c8->opiodr()b98->opipls()->opiexe()->ksuvrl()c->44c0->-> 1 ->rpiswu2()c0->rpidru()->skgmstack()c4->rpidrus()c8->opiodr()b98->opipls()->opiexe()->44c0->-> 1 ->rpiswu2()c0->rpidru()->skgmstack()c4->rpidrus()c8->opiodr()->ksuprc()c->44c0->->
é¢æ°åãauddftã/ãaudbegãã¯ãç£æ»ã«é¢é£ãããã®ã瀺ããŠããå ŽåããããŸããããã©ã¡ãŒã¿ãaudit_trail = DBããé€ããç£æ»ãªãã·ã§ã³ã¯ããŒã¿ããŒã¹ã§ã¢ã¯ãã£ãåãããŠããŸããã Alex Fatkulinã¯æè¿ãå«ãŸããŠããç£æ»ãªãã·ã§ã³ã11.2.0.1ã®é床ãäœäžãããåé¡ã®èª¬æãå ¬éããŸããããã¡ãããaudit_trail = NONEãã©ã¡ãŒã¿ãŒã11.1.07ãŸãã¯11.2.0.1ã«èšå®ãããšãé床äœäžã¯ããã»ã©æçœã§ã¯ãããŸããã§ããã ããã¯ãå®éã«ã¯ç£æ»ã«é¢é£ããã³ãŒãã®äžéšãããããšãæå³ããŸãã ãã ããããã¯åé¡ã解決ããŸããã§ãã-ãŸã å€§å¹ ãªæžéããããŸããã
PGA / UGAã¡ã¢ãªãã³ããåæããéã«éèŠãªèŠ³å¯ãè¡ãããŸããã
PGA / UGAãã³ãã«ã¯ãXMLã®æäœã«é¢é£ããæ°åäžãã®éåžžã«å°ããªããŒã¿ãå«ãŸããŠããŸããïŒ "qmxdpls_subhea"ïŒã ãããã£ãŠããšã©ãŒã¯XMLã®ã¡ã¢ãªç®¡çã«é¢é£ããäœãã«é¢é£ããŠãããšããä»®å®ãæããã«ãªããŸããã
ãããã£ãŠãXMLåŠçãæ åœããã³ãŒãã®éšåã«æ³šç®ããŸããã ãã°ãããã«èŠã€ãããŸãããã³ãŒãã«DBMS_XMLDOM.FREEDOCUMENTã®åŒã³åºãããããŸããã§ããã
ã©ãããããã®ãã°ã¯æåããã³ãŒãã«ååšããŠããŸããããã¢ããªã±ãŒã·ã§ã³ã¯10.2åãã«éçºãããŠããããã®ãããªé床ã®äœäžã¯ãããŸããã§ããããPGA / UGAã¡ã¢ãªæ¶è²»ã®å¢å ãäžæLOBã®ãªãŒã¯ãªã©ãåé¡ã®åæ§ã®çç¶ããããŸããããåãã¹ããŒããŠã³ã¯ãããŸããã§ããã ã£ãã ãã°ããåã«ããŒã¿ããŒã¹ãããŒãžã§ã³11.1.0.7ã«è»¢éãããåŸãã¹ããŒããŠã³ã®åé¡ãçºçããŸããã
ãããã£ãŠããã®åé¡ã¯ãã³ãŒãã«freedocumentã¢ã¯ã»ã¹ã³ãŒããè¿œå ãŸãã¯åé€ããã ãã§è§£æ±ºãŸãã¯çºèŠã§ããŸãã
ããã«ãããã»ãšãã©ã®å ŽåãããŒã¿ããŒã¹11.1.0.7以éã䜿çšããŠããªã³ããã³ãã§åé¡ãåçŸã§ããå žåçãªãã¹ãã·ããªãªãéçºããããšãã§ããŸããã
泚ïŒãã®åé¡ã¯ãç¹å®ã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®Oracleããªã¢ã³ãã«é¢é£ããŠããããã§ãã Linux x64çšã®Oracle 11.1.0.7ã®åäœã¯å€å°ç°ãªããŸããäžéšã®SQLã¯ãšãªã®ã¿ãé ããªããŸãããããã¯ãAIXããŒãžã§ã³ã䜿çšããŠãããšãã«çºçããŸããã
drop table t_testloop; purge table t_testloop; create table t_testloop ( id integer not null , vc varchar2(255) , constraint t_testloop_pk primary key (id) ) ; insert into t_testloop ( id , vc ) select level as id , rpad('x', 100, 'x') as vc from dual connect by level <= 100; commit; exec dbms_stats.gather_table_stats(null, 'T_TESTLOOP') -- This is supposed to be a INDEX UNIQUE SCAN + TABLE ACCESS BY ROWID explain plan for select id , vc from t_testloop where id = to_number(:x); set linesize 160 set pagesize 999 select * from table(dbms_xplan.display); set timing on echo on serveroutput on -- This is the normal (reference) execution time for running -- the simple statement a thousand times declare procedure check_key as x integer; n_id integer; s_vc varchar2(255); begin x := 42 * 3; select id , vc into n_id , s_vc from t_testloop where id = x; exception when NO_DATA_FOUND then null; end; begin for i in 1..1000 loop check_key; end loop; end; / -- "Deterministic" randomness :-)) exec dbms_random.seed(0) declare start_time number; end_time number; -- Generate some CLOB containing XML -- Note that it looks like the CLOB needs -- to be different for every iteration -- otherwise the issue couldn't be reproduced function return_clob return clob as the_lobclob; s_name varchar2(20); n_sal integer; s_job varchar2(20); begin the_lob := '<root> '; for i in 1..20 loop s_name := dbms_random.string('U', trunc(dbms_random.value(1, 21))); n_sal := trunc(dbms_random.value(1, 1001)); s_job := dbms_random.string('U', trunc(dbms_random.value(1, 21))); the_lob := the_lob || '<emp attr1="val1" attr2="val2" attr3="val3"> <empno attr1="val1" attr2="val2" attr3="val3">' || to_char(i, 'TM') || '</empno> <name attr1="val1" attr2="val2" attr3="val3">' || s_name || '</name> <sal attr1="val1" attr2="val2" attr3="val3">' || to_char(n_sal, 'TM') || '</sal> <job attr1="val1" attr2="val2" attr3="val3">' || s_job || '</job> </emp> '; end loop; the_lob := the_lob || '</root>'; return the_lob; end return_clob; -- Some usage of the PL/SQL XML DOM API -- Some dummy processing of the attributes of the given node procedure process_attributes ( in_nodedbms_xmldom.DOMNode ) is len number; n dbms_xmldom.DOMNode; nnmdbms_xmldom.DOMNamedNodeMap; key varchar2(1000); val varchar2(32767); BEGIN nnm := dbms_xmldom.getAttributes(in_node); if (dbms_xmldom.isNull(nnm) = FALSE) then len := dbms_xmldom.getLength(nnm); -- loop through attributes for i in 0..len-1 loop n := dbms_xmldom.item(nnm, i); key := dbms_xmldom.getNodeName(n); val := dbms_xmldom.getNodeValue(n); end loop; end if; end process_attributes; -- Some usage of the PL/SQL XML DOM API -- Recursively walk the nodes of the DOM -- and call the attribute processing per node procedure walk_node ( in_nodedbms_xmldom.DOMNode ) is nldbms_xmldom.DOMNodeList; len number; n dbms_xmldom.DOMNode; node_name varchar2(100); begin -- loop through elements node_name:=dbms_xmldom.getNodeName(in_node); process_attributes(in_node); nl := dbms_xmldom.getChildNodes(in_node); len := dbms_xmldom.getLength(nl); for i in 0..len-1 loop n := dbms_xmldom.item(nl, i); node_name := dbms_xmldom.getNodeName(n); walk_node(n); end loop; end walk_node; -- The main procedure procedureprocess_xml_clob as the_lobclob; varXMLType; doc dbms_xmldom.DOMDocument; root dbms_xmldom.DOMNode; root_tag varchar2(100); begin -- Get the CLOB with the XML the_lob := return_clob; -- Instantiate an XMLTYPE var := xmltype(the_lob); -- Generate a new DOM document from the XMLType -- This seems to allocate a temporary LOB under the covers doc := dbms_xmldom.newDOMDocument(var); -- Some rudimentary XML DOM processing root := dbms_xmldom.makeNode(dbms_xmldom.getDocumentElement(doc)); root_tag := dbms_xmldom.getNodeName(root); -- If you want to burn more CPU to exaggerate the effect -- uncomment this -- walk_node(root); -- This omission here causes a significant PGA/UGA memory leak -- and causes version 11.1 and 11.2 to slow down everything -- in this session -- Version 10.2 suffers from the same symptoms but doesn't slow down --DBMS_XMLDOM.freeDocument(doc); end; begin -- Run this a thousand times and measure / output the runtime per execution for i in 1..1000 loop start_time := dbms_utility.get_time; process_xml_clob; end_time := dbms_utility.get_time; dbms_output.put_line('Run ' || to_char(i, 'TM') || ': Time (in seconds)= ' || ((end_time - start_time)/100)); end loop; end; / -- Do the simple statement again a thousand times -- Notice the difference in runtime when using 11.1.0.7 or 11.2.0.1 declare procedure check_key as x integer; n_id integer; s_vc varchar2(255); begin x := 42 * 3; select id , vc into n_id , s_vc from t_testloop where id = x; exception when NO_DATA_FOUND then null; end; begin for i in 1..1000 loop check_key; end loop; end; /
äžèšã®éèŠãªè¡ã¯ãDBMS_XMLDOM.FREEDOCUMENTãã§ãã ããŒã¿ããŒã¹ã®äœéããŒãžã§ã³ïŒ11.1.0.7ãŸãã¯11.2.0.1ïŒã§FREEDOCUMENTãåŒã³åºããã«ã¹ã¯ãªãããå®è¡ãããšãéåžžãçµæã¯æ¬¡ã®ããã«ãªããŸãã
SQL> declare 2 procedure check_key 3 as 4 x integer; 5 n_id integer; 6 s_vc varchar2(255); 7 begin 8 x := 42 * 3; 9 select 10 id 11 , vc 12 into 13 n_id 14 , s_vc 15 from 16 t_testloop 17 where 18 id = x; 19 exception 20 when NO_DATA_FOUND then 21 null; 22 end; 23 begin 24 for i in 1..1000 loop 25 check_key; 26 end loop; 27 end; 28 / PL/SQL procedure successfully completed. Elapsed: 00:00:00.94 . . . Run 1: Time (in seconds)= .49 Run 2: Time (in seconds)= .08 Run 3: Time (in seconds)= .08 Run 4: Time (in seconds)= .08 Run 5: Time (in seconds)= .05 Run 6: Time (in seconds)= .03 Run 7: Time (in seconds)= .03 Run 8: Time (in seconds)= .03 Run 9: Time (in seconds)= .03 Run 10: Time (in seconds)= .02 Run 11: Time (in seconds)= .03 Run 12: Time (in seconds)= .03 Run 13: Time (in seconds)= .03 Run 14: Time (in seconds)= .03 Run 15: Time (in seconds)= .03 Run 16: Time (in seconds)= .03 Run 17: Time (in seconds)= .02 Run 18: Time (in seconds)= .03 Run 19: Time (in seconds)= .03 Run 20: Time (in seconds)= .03 Run 21: Time (in seconds)= .03 Run 22: Time (in seconds)= .03 Run 23: Time (in seconds)= .03 Run 24: Time (in seconds)= .03 Run 25: Time (in seconds)= .03 . . . Run 287: Time (in seconds)= .03 Run 288: Time (in seconds)= .03 Run 289: Time (in seconds)= .03 Run 290: Time (in seconds)= .03 Run 291: Time (in seconds)= .02 Run 292: Time (in seconds)= .03 Run 293: Time (in seconds)= .03 Run 294: Time (in seconds)= .03 Run 295: Time (in seconds)= .03 Run 296: Time (in seconds)= .03 Run 297: Time (in seconds)= .03 Run 298: Time (in seconds)= .02 Run 299: Time (in seconds)= .03 Run 300: Time (in seconds)= .03 Run 301: Time (in seconds)= .03 Run 302: Time (in seconds)= .03 Run 303: Time (in seconds)= .17 Run 304: Time (in seconds)= .17 Run 305: Time (in seconds)= .17 Run 306: Time (in seconds)= .17 Run 307: Time (in seconds)= .17 Run 308: Time (in seconds)= .17 Run 309: Time (in seconds)= .17 Run 310: Time (in seconds)= .17 Run 311: Time (in seconds)= .18 Run 312: Time (in seconds)= .17 Run 313: Time (in seconds)= .18 Run 314: Time (in seconds)= .18 Run 315: Time (in seconds)= .18 Run 316: Time (in seconds)= .17 Run 317: Time (in seconds)= .19 Run 318: Time (in seconds)= .18 Run 319: Time (in seconds)= .18 Run 320: Time (in seconds)= .19 Run 321: Time (in seconds)= .18 Run 322: Time (in seconds)= .19 . . . Run 973: Time (in seconds)= .82 Run 974: Time (in seconds)= .83 Run 975: Time (in seconds)= .83 Run 976: Time (in seconds)= .82 Run 977: Time (in seconds)= .83 Run 978: Time (in seconds)= .83 Run 979: Time (in seconds)= .82 Run 980: Time (in seconds)= .82 Run 981: Time (in seconds)= .83 Run 982: Time (in seconds)= .82 Run 983: Time (in seconds)= .83 Run 984: Time (in seconds)= .83 Run 985: Time (in seconds)= .82 Run 986: Time (in seconds)= .84 Run 987: Time (in seconds)= .83 Run 988: Time (in seconds)= .86 Run 989: Time (in seconds)= .84 Run 990: Time (in seconds)= .83 Run 991: Time (in seconds)= .85 Run 992: Time (in seconds)= .84 Run 993: Time (in seconds)= .84 Run 994: Time (in seconds)= .85 Run 995: Time (in seconds)= .84 Run 996: Time (in seconds)= .85 Run 997: Time (in seconds)= .84 Run 998: Time (in seconds)= .87 Run 999: Time (in seconds)= .84 Run 1000: Time (in seconds)= .85 PL/SQL procedure successfully completed. Elapsed: 00:06:00.49 SQL> SQL> declare 2 procedure check_key 3 as 4 x integer; 5 n_id integer; 6 s_vc varchar2(255); 7 begin 8 x := 42 * 3; 9 select 10 id 11 , vc 12 into 13 n_id 14 , s_vc 15 from 16 t_testloop 17 where 18 id = x; 19 exception 20 when NO_DATA_FOUND then 21 null; 22 end; 23 begin 24 for i in 1..1000 loop 25 check_key; 26 end loop; 27 end; 28 / PL/SQL procedure successfully completed. Elapsed: 00:00:03.02 SQL>
泚æããŠãã ããã äžå®ã®å埩åæ°ã®åŸãã³ãã³ãã®å®è¡ã¯ãŸããŸãé ããªããŸãã ããã«èå³æ·±ãã®ã¯ã1,000ã®SQLã¯ãšãªã®åçŽãªãµã€ã¯ã«ãããã®ã³ãŒããããã¯ã®å®è¡åãããããªãé·ãå®è¡æéãå¿ èŠãšããããšã§ãã
çµ±èšã®åéäžããŸãã¯ãã®ã³ãŒããããã¯ã®å®è¡äžã«V $ PROCESSããã³V $ TEMPORARY_LOBSãå®è¡äžã«ãPGA / UGAã®æ¶è²»ã芳å¯ããããšãã§ããŸãã
ããŒãžã§ã³10.2.0.4ã§åãæäœãå®è¡ãããšãåé¡ã®åãçç¶ã衚瀺ãããŸãããã©ã³ã¿ã€ã ã¯å°ãªããšã1,000åã®ç¹°ãè¿ãã«å¯ŸããŠå®å®ããŠããŸãã ã·ã¹ãã ãæ¶è²»ããã¡ã¢ãªã®éãå¢ãç¶ããããšã§åé¡ãçºçãããšããæ¥ãããšã¯æããã§ãããããã¯ç§ãã¡ã®åé¡ãšã¯é¢ä¿ãããŸããã
DBMS_XMLDOM.FREEDOCUMENTã«æ£ããã¢ã¯ã»ã¹ãããšã11.1.0.7ããã³11.2.0.1ã®ã³ãŒãã®åãéšåãããã»ã¹ã®å®å®ããå®è¡æéãæäŸããŸãïŒPGA / UGAã¡ã¢ãªãŸãã¯äžæLOBã®æ¶è²»ã®å¢å ã¯ãããŸããïŒã
Nigel Nobleã¯æè¿ãããŒãžã§ã³11.1.0.7ã§ã®ã¿è¡šç€ºããããããŒãžã§ã³10.2.0.4ã§ã¯èŠã€ãããªãPL / SQLã¡ã¢ãªã®åé¡ã«é¢ããããã°æçš¿ãæçš¿ããŸããã
Alex FatkulinãšNigel Nobleãææããåé¡ã¯ãããã§èª¬æããåé¡ãšå¿ ãããé¢é£ããŠããããã§ã¯ãããŸããããOracleããŒãžã§ã³11ã®ãªãªãŒã¹ã§ã¡ã¢ãªç®¡çã«ããã€ãã®å€æŽãå°å ¥ãããããšã瀺ããŠããŸãïŒããããç¹å®ã®æ¡ä»¶äžã§ä»¥åã®ããŒãžã§ã³ãšã¯ç°ãªãåäœãããèªåã¡ã¢ãªç®¡çæ©èœAMMãŸãã¯memory_targetãã©ã¡ãŒã¿ãŒã®å®è£ ã
3æ24æ¥ã«ãã¢ã¹ã¯ã¯ã¯ãOracleããŒã¿ããŒã¹ã®ããã©ãŒãã³ã¹ã®åé¡ã解決ãã Randolph Geist ã«ããã¯ãŒã¯ã·ã§ãããéå¬ããŸãã