|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 /* 00003 V5.14 8 Sept 2011 (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved. 00004 Released under both BSD license and Lesser GPL library license. 00005 Whenever there is any discrepancy between the two licenses, 00006 the BSD license will take precedence. See License.txt. 00007 Set tabs to 4 for best viewing. 00008 00009 Latest version is available at http://adodb.sourceforge.net 00010 00011 Library for basic performance monitoring and tuning 00012 00013 */ 00014 00015 // security - hide paths 00016 if (!defined('ADODB_DIR')) die(); 00017 00018 00019 class perf_oci8 extends ADODB_perf{ 00020 00021 var $noShowIxora = 15; // if the sql for suspicious sql is taking too long, then disable ixora 00022 00023 var $tablesSQL = "select segment_name as \"tablename\", sum(bytes)/1024 as \"size_in_k\",tablespace_name as \"tablespace\",count(*) \"extents\" from sys.user_extents 00024 group by segment_name,tablespace_name"; 00025 00026 var $version; 00027 00028 var $createTableSQL = "CREATE TABLE adodb_logsql ( 00029 created date NOT NULL, 00030 sql0 varchar(250) NOT NULL, 00031 sql1 varchar(4000) NOT NULL, 00032 params varchar(4000), 00033 tracer varchar(4000), 00034 timer decimal(16,6) NOT NULL 00035 )"; 00036 00037 var $settings = array( 00038 'Ratios', 00039 'data cache hit ratio' => array('RATIOH', 00040 "select round((1-(phy.value / (cur.value + con.value)))*100,2) 00041 from v\$sysstat cur, v\$sysstat con, v\$sysstat phy 00042 where cur.name = 'db block gets' and 00043 con.name = 'consistent gets' and 00044 phy.name = 'physical reads'", 00045 '=WarnCacheRatio'), 00046 00047 'sql cache hit ratio' => array( 'RATIOH', 00048 'select round(100*(sum(pins)-sum(reloads))/sum(pins),2) from v$librarycache', 00049 'increase <i>shared_pool_size</i> if too ratio low'), 00050 00051 'datadict cache hit ratio' => array('RATIOH', 00052 "select 00053 round((1 - (sum(getmisses) / (sum(gets) + 00054 sum(getmisses))))*100,2) 00055 from v\$rowcache", 00056 'increase <i>shared_pool_size</i> if too ratio low'), 00057 00058 'memory sort ratio' => array('RATIOH', 00059 "SELECT ROUND((100 * b.VALUE) /DECODE ((a.VALUE + b.VALUE), 00060 0,1,(a.VALUE + b.VALUE)),2) 00061 FROM v\$sysstat a, 00062 v\$sysstat b 00063 WHERE a.name = 'sorts (disk)' 00064 AND b.name = 'sorts (memory)'", 00065 "% of memory sorts compared to disk sorts - should be over 95%"), 00066 00067 'IO', 00068 'data reads' => array('IO', 00069 "select value from v\$sysstat where name='physical reads'"), 00070 00071 'data writes' => array('IO', 00072 "select value from v\$sysstat where name='physical writes'"), 00073 00074 'Data Cache', 00075 00076 'data cache buffers' => array( 'DATAC', 00077 "select a.value/b.value from v\$parameter a, v\$parameter b 00078 where a.name = 'db_cache_size' and b.name= 'db_block_size'", 00079 'Number of cache buffers. Tune <i>db_cache_size</i> if the <i>data cache hit ratio</i> is too low.'), 00080 'data cache blocksize' => array('DATAC', 00081 "select value from v\$parameter where name='db_block_size'", 00082 '' ), 00083 00084 'Memory Pools', 00085 'Mem Max Target (11g+)' => array( 'DATAC', 00086 "select value from v\$parameter where name = 'memory_max_target'", 00087 'The memory_max_size is the maximum value to which memory_target can be set.' ), 00088 'Memory target (11g+)' => array( 'DATAC', 00089 "select value from v\$parameter where name = 'memory_target'", 00090 'If memory_target is defined then SGA and PGA targets are consolidated into one memory_target.' ), 00091 'SGA Max Size' => array( 'DATAC', 00092 "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'sga_max_size'", 00093 'The sga_max_size is the maximum value to which sga_target can be set.' ), 00094 'SGA target' => array( 'DATAC', 00095 "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'sga_target'", 00096 'If sga_target is defined then data cache, shared, java and large pool size can be 0. This is because all these pools are consolidated into one sga_target.' ), 00097 'PGA aggr target' => array( 'DATAC', 00098 "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'pga_aggregate_target'", 00099 'If pga_aggregate_target is defined then this is the maximum memory that can be allocated for cursor operations such as sorts, group by, joins, merges. When in doubt, set it to 20% of sga_target.' ), 00100 'data cache size' => array('DATAC', 00101 "select value from v\$parameter where name = 'db_cache_size'", 00102 'db_cache_size' ), 00103 'shared pool size' => array('DATAC', 00104 "select value from v\$parameter where name = 'shared_pool_size'", 00105 'shared_pool_size, which holds shared sql, stored procedures, dict cache and similar shared structs' ), 00106 'java pool size' => array('DATAJ', 00107 "select value from v\$parameter where name = 'java_pool_size'", 00108 'java_pool_size' ), 00109 'large pool buffer size' => array('CACHE', 00110 "select value from v\$parameter where name='large_pool_size'", 00111 'this pool is for large mem allocations (not because it is larger than shared pool), for MTS sessions, parallel queries, io buffers (large_pool_size) ' ), 00112 00113 'dynamic memory usage' => array('CACHE', "select '-' from dual", '=DynMemoryUsage'), 00114 00115 'Connections', 00116 'current connections' => array('SESS', 00117 'select count(*) from sys.v_$session where username is not null', 00118 ''), 00119 'max connections' => array( 'SESS', 00120 "select value from v\$parameter where name='sessions'", 00121 ''), 00122 00123 'Memory Utilization', 00124 'data cache utilization ratio' => array('RATIOU', 00125 "select round((1-bytes/sgasize)*100, 2) 00126 from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f 00127 where name = 'free memory' and pool = 'shared pool'", 00128 'Percentage of data cache actually in use - should be over 85%'), 00129 00130 'shared pool utilization ratio' => array('RATIOU', 00131 'select round((sga.bytes/case when p.value=0 then sga.bytes else to_number(p.value) end)*100,2) 00132 from v$sgastat sga, v$parameter p 00133 where sga.name = \'free memory\' and sga.pool = \'shared pool\' 00134 and p.name = \'shared_pool_size\'', 00135 'Percentage of shared pool actually used - too low is bad, too high is worse'), 00136 00137 'large pool utilization ratio' => array('RATIOU', 00138 "select round((1-bytes/sgasize)*100, 2) 00139 from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f 00140 where name = 'free memory' and pool = 'large pool'", 00141 'Percentage of large_pool actually in use - too low is bad, too high is worse'), 00142 'sort buffer size' => array('CACHE', 00143 "select value from v\$parameter where name='sort_area_size'", 00144 'max in-mem sort_area_size (per query), uses memory in pga' ), 00145 00146 /*'pga usage at peak' => array('RATIOU', 00147 '=PGA','Mb utilization at peak transactions (requires Oracle 9i+)'),*/ 00148 'Transactions', 00149 'rollback segments' => array('ROLLBACK', 00150 "select count(*) from sys.v_\$rollstat", 00151 ''), 00152 00153 'peak transactions' => array('ROLLBACK', 00154 "select max_utilization tx_hwm 00155 from sys.v_\$resource_limit 00156 where resource_name = 'transactions'", 00157 'Taken from high-water-mark'), 00158 'max transactions' => array('ROLLBACK', 00159 "select value from v\$parameter where name = 'transactions'", 00160 'max transactions / rollback segments < 3.5 (or transactions_per_rollback_segment)'), 00161 'Parameters', 00162 'cursor sharing' => array('CURSOR', 00163 "select value from v\$parameter where name = 'cursor_sharing'", 00164 'Cursor reuse strategy. Recommended is FORCE (8i+) or SIMILAR (9i+). See <a href=http://www.praetoriate.com/oracle_tips_cursor_sharing.htm>cursor_sharing</a>.'), 00165 /* 00166 'cursor reuse' => array('CURSOR', 00167 "select count(*) from (select sql_text_wo_constants, count(*) 00168 from t1 00169 group by sql_text_wo_constants 00170 having count(*) > 100)",'These are sql statements that should be using bind variables'),*/ 00171 'index cache cost' => array('COST', 00172 "select value from v\$parameter where name = 'optimizer_index_caching'", 00173 '=WarnIndexCost'), 00174 'random page cost' => array('COST', 00175 "select value from v\$parameter where name = 'optimizer_index_cost_adj'", 00176 '=WarnPageCost'), 00177 'Waits', 00178 'Recent wait events' => array('WAITS','select \'Top 5 events\' from dual','=TopRecentWaits'), 00179 // 'Historical wait SQL' => array('WAITS','select \'Last 2 days\' from dual','=TopHistoricalWaits'), -- requires AWR license 00180 'Backup', 00181 'Achivelog Mode' => array('BACKUP', 'select log_mode from v$database', '=LogMode'), 00182 00183 'DBID' => array('BACKUP','select dbid from v$database','Primary key of database, used for recovery with an RMAN Recovery Catalog'), 00184 'Archive Log Dest' => array('BACKUP', "SELECT NVL(v1.value,v2.value) 00185 FROM v\$parameter v1, v\$parameter v2 WHERE v1.name='log_archive_dest' AND v2.name='log_archive_dest_10'", ''), 00186 00187 'Flashback Area' => array('BACKUP', "select nvl(value,'Flashback Area not used') from v\$parameter where name=lower('DB_RECOVERY_FILE_DEST')", 'Flashback area is a folder where all backup data and logs can be stored and managed by Oracle. If Error: message displayed, then it is not in use.'), 00188 00189 'Flashback Usage' => array('BACKUP', "select nvl('-','Flashback Area not used') from v\$parameter where name=lower('DB_RECOVERY_FILE_DEST')", '=FlashUsage', 'Flashback area usage.'), 00190 00191 'Control File Keep Time' => array('BACKUP', "select value from v\$parameter where name='control_file_record_keep_time'",'No of days to keep RMAN info in control file. Recommended set to x2 or x3 times the frequency of your full backup.'), 00192 'Recent RMAN Jobs' => array('BACKUP', "select '-' from dual", "=RMAN"), 00193 00194 // 'Control File Keep Time' => array('BACKUP', "select value from v\$parameter where name='control_file_record_keep_time'",'No of days to keep RMAN info in control file. I recommend it be set to x2 or x3 times the frequency of your full backup.'), 00195 00196 false 00197 00198 ); 00199 00200 00201 function perf_oci8(&$conn) 00202 { 00203 global $gSQLBlockRows; 00204 00205 $gSQLBlockRows = 1000; 00206 $savelog = $conn->LogSQL(false); 00207 $this->version = $conn->ServerInfo(); 00208 $conn->LogSQL($savelog); 00209 $this->conn = $conn; 00210 } 00211 00212 function LogMode() 00213 { 00214 $mode = $this->conn->GetOne("select log_mode from v\$database"); 00215 00216 if ($mode == 'ARCHIVELOG') return 'To turn off archivelog:<br> 00217 <pre><font size=-2> 00218 SQLPLUS> connect sys as sysdba; 00219 SQLPLUS> shutdown immediate; 00220 00221 SQLPLUS> startup mount exclusive; 00222 SQLPLUS> alter database noarchivelog; 00223 SQLPLUS> alter database open; 00224 </font></pre>'; 00225 00226 return 'To turn on archivelog:<br> 00227 <pre><font size=-2> 00228 SQLPLUS> connect sys as sysdba; 00229 SQLPLUS> shutdown immediate; 00230 00231 SQLPLUS> startup mount exclusive; 00232 SQLPLUS> alter database archivelog; 00233 SQLPLUS> archive log start; 00234 SQLPLUS> alter database open; 00235 </font></pre>'; 00236 } 00237 00238 function TopRecentWaits() 00239 { 00240 00241 $rs = $this->conn->Execute("select * from ( 00242 select event, round(100*time_waited/(select sum(time_waited) from v\$system_event where wait_class <> 'Idle'),1) \"% Wait\", 00243 total_waits,time_waited, average_wait,wait_class from v\$system_event where wait_class <> 'Idle' order by 2 desc 00244 ) where rownum <=5"); 00245 00246 $ret = rs2html($rs,false,false,false,false); 00247 return " <p>".$ret." </p>"; 00248 00249 } 00250 00251 function TopHistoricalWaits() 00252 { 00253 $days = 2; 00254 00255 $rs = $this->conn->Execute("select * from ( SELECT 00256 b.wait_class,B.NAME, 00257 round(sum(wait_time+TIME_WAITED)/1000000) waitsecs, 00258 parsing_schema_name, 00259 C.SQL_TEXT, a.sql_id 00260 FROM V\$ACTIVE_SESSION_HISTORY A 00261 join V\$EVENT_NAME B on A.EVENT# = B.EVENT# 00262 join V\$SQLAREA C on A.SQL_ID = C.SQL_ID 00263 WHERE A.SAMPLE_TIME BETWEEN sysdate-$days and sysdate 00264 and parsing_schema_name not in ('SYS','SYSMAN','DBSNMP','SYSTEM') 00265 GROUP BY b.wait_class,parsing_schema_name,C.SQL_TEXT, B.NAME,A.sql_id 00266 order by 3 desc) where rownum <=10"); 00267 00268 $ret = rs2html($rs,false,false,false,false); 00269 return " <p>".$ret." </p>"; 00270 00271 } 00272 00273 function RMAN() 00274 { 00275 $rs = $this->conn->Execute("select * from (select start_time, end_time, operation, status, mbytes_processed, output_device_type 00276 from V\$RMAN_STATUS order by start_time desc) where rownum <=10"); 00277 00278 $ret = rs2html($rs,false,false,false,false); 00279 return " <p>".$ret." </p>"; 00280 00281 } 00282 function DynMemoryUsage() 00283 { 00284 if (@$this->version['version'] >= 11) { 00285 $rs = $this->conn->Execute("select component, current_size/1024./1024 as \"CurrSize (M)\" from V\$MEMORY_DYNAMIC_COMPONENTS"); 00286 00287 } else 00288 $rs = $this->conn->Execute("select name, round(bytes/1024./1024,2) as \"CurrSize (M)\" from V\$sgainfo"); 00289 00290 00291 $ret = rs2html($rs,false,false,false,false); 00292 return " <p>".$ret." </p>"; 00293 } 00294 00295 function FlashUsage() 00296 { 00297 $rs = $this->conn->Execute("select * from V\$FLASH_RECOVERY_AREA_USAGE"); 00298 $ret = rs2html($rs,false,false,false,false); 00299 return " <p>".$ret." </p>"; 00300 } 00301 00302 function WarnPageCost($val) 00303 { 00304 if ($val == 100 && $this->version['version'] < 10) $s = '<font color=red><b>Too High</b>. </font>'; 00305 else $s = ''; 00306 00307 return $s.'Recommended is 20-50 for TP, and 50 for data warehouses. Default is 100. See <a href=http://www.dba-oracle.com/oracle_tips_cost_adj.htm>optimizer_index_cost_adj</a>. '; 00308 } 00309 00310 function WarnIndexCost($val) 00311 { 00312 if ($val == 0 && $this->version['version'] < 10) $s = '<font color=red><b>Too Low</b>. </font>'; 00313 else $s = ''; 00314 00315 return $s.'Percentage of indexed data blocks expected in the cache. 00316 Recommended is 20 (fast disk array) to 30 (slower hard disks). Default is 0. 00317 See <a href=http://www.dba-oracle.com/oracle_tips_cbo_part1.htm>optimizer_index_caching</a>.'; 00318 } 00319 00320 function PGA() 00321 { 00322 00323 //if ($this->version['version'] < 9) return 'Oracle 9i or later required'; 00324 } 00325 function PGA_Advice() 00326 { 00327 $t = "<h3>PGA Advice Estimate</h3>"; 00328 if ($this->version['version'] < 9) return $t.'Oracle 9i or later required'; 00329 00330 $rs = $this->conn->Execute('select a.MB, 00331 case when a.targ = 1 then \'<<= Current \' 00332 when a.targ < 1 or a.pct <= b.pct then null 00333 else 00334 \'- BETTER than Current by \'||round(a.pct/b.pct*100-100,2)||\'%\' end as "Percent Improved", 00335 a.targ as "PGA Size Factor",a.pct "% Perf" 00336 from 00337 (select round(pga_target_for_estimate/1024.0/1024.0,0) MB, 00338 pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r 00339 from v$pga_target_advice) a left join 00340 (select round(pga_target_for_estimate/1024.0/1024.0,0) MB, 00341 pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r 00342 from v$pga_target_advice) b on 00343 a.r = b.r+1 where 00344 b.pct < 100'); 00345 if (!$rs) return $t."Only in 9i or later"; 00346 // $rs->Close(); 00347 if ($rs->EOF) return $t."PGA could be too big"; 00348 00349 return $t.rs2html($rs,false,false,true,false); 00350 } 00351 00352 function Explain($sql,$partial=false) 00353 { 00354 $savelog = $this->conn->LogSQL(false); 00355 $rs = $this->conn->SelectLimit("select ID FROM PLAN_TABLE"); 00356 if (!$rs) { 00357 echo "<p><b>Missing PLAN_TABLE</b></p> 00358 <pre> 00359 CREATE TABLE PLAN_TABLE ( 00360 STATEMENT_ID VARCHAR2(30), 00361 TIMESTAMP DATE, 00362 REMARKS VARCHAR2(80), 00363 OPERATION VARCHAR2(30), 00364 OPTIONS VARCHAR2(30), 00365 OBJECT_NODE VARCHAR2(128), 00366 OBJECT_OWNER VARCHAR2(30), 00367 OBJECT_NAME VARCHAR2(30), 00368 OBJECT_INSTANCE NUMBER(38), 00369 OBJECT_TYPE VARCHAR2(30), 00370 OPTIMIZER VARCHAR2(255), 00371 SEARCH_COLUMNS NUMBER, 00372 ID NUMBER(38), 00373 PARENT_ID NUMBER(38), 00374 POSITION NUMBER(38), 00375 COST NUMBER(38), 00376 CARDINALITY NUMBER(38), 00377 BYTES NUMBER(38), 00378 OTHER_TAG VARCHAR2(255), 00379 PARTITION_START VARCHAR2(255), 00380 PARTITION_STOP VARCHAR2(255), 00381 PARTITION_ID NUMBER(38), 00382 OTHER LONG, 00383 DISTRIBUTION VARCHAR2(30) 00384 ); 00385 </pre>"; 00386 return false; 00387 } 00388 00389 $rs->Close(); 00390 // $this->conn->debug=1; 00391 00392 if ($partial) { 00393 $sqlq = $this->conn->qstr($sql.'%'); 00394 $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq"); 00395 if ($arr) { 00396 foreach($arr as $row) { 00397 $sql = reset($row); 00398 if (crc32($sql) == $partial) break; 00399 } 00400 } 00401 } 00402 00403 $s = "<p><b>Explain</b>: ".htmlspecialchars($sql)."</p>"; 00404 00405 $this->conn->BeginTrans(); 00406 $id = "ADODB ".microtime(); 00407 00408 $rs = $this->conn->Execute("EXPLAIN PLAN SET STATEMENT_ID='$id' FOR $sql"); 00409 $m = $this->conn->ErrorMsg(); 00410 if ($m) { 00411 $this->conn->RollbackTrans(); 00412 $this->conn->LogSQL($savelog); 00413 $s .= "<p>$m</p>"; 00414 return $s; 00415 } 00416 $rs = $this->conn->Execute(" 00417 select 00418 '<pre>'||lpad('--', (level-1)*2,'-') || trim(operation) || ' ' || trim(options)||'</pre>' as Operation, 00419 object_name,COST,CARDINALITY,bytes 00420 FROM plan_table 00421 START WITH id = 0 and STATEMENT_ID='$id' 00422 CONNECT BY prior id=parent_id and statement_id='$id'"); 00423 00424 $s .= rs2html($rs,false,false,false,false); 00425 $this->conn->RollbackTrans(); 00426 $this->conn->LogSQL($savelog); 00427 $s .= $this->Tracer($sql,$partial); 00428 return $s; 00429 } 00430 00431 00432 function CheckMemory() 00433 { 00434 if ($this->version['version'] < 9) return 'Oracle 9i or later required'; 00435 00436 $rs = $this->conn->Execute(" 00437 select a.name Buffer_Pool, b.size_for_estimate as cache_mb_estimate, 00438 case when b.size_factor=1 then 00439 '<<= Current' 00440 when a.estd_physical_read_factor-b.estd_physical_read_factor > 0.001 and b.estd_physical_read_factor<1 then 00441 '- BETTER than current by ' || round((1-b.estd_physical_read_factor)/b.estd_physical_read_factor*100,2) || '%' 00442 else ' ' end as RATING, 00443 b.estd_physical_read_factor \"Phys. Reads Factor\", 00444 round((a.estd_physical_read_factor-b.estd_physical_read_factor)/b.estd_physical_read_factor*100,2) as \"% Improve\" 00445 from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r,name from v\$db_cache_advice order by name,1) a , 00446 (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r,name from v\$db_cache_advice order by name,1) b 00447 where a.r = b.r-1 and a.name = b.name 00448 "); 00449 if (!$rs) return false; 00450 00451 /* 00452 The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size 00453 */ 00454 $s = "<h3>Data Cache Advice Estimate</h3>"; 00455 if ($rs->EOF) { 00456 $s .= "<p>Cache that is 50% of current size is still too big</p>"; 00457 } else { 00458 $s .= "Ideal size of Data Cache is when %BETTER gets close to zero."; 00459 $s .= rs2html($rs,false,false,false,false); 00460 } 00461 return $s.$this->PGA_Advice(); 00462 } 00463 00464 /* 00465 Generate html for suspicious/expensive sql 00466 */ 00467 function tohtml(&$rs,$type) 00468 { 00469 $o1 = $rs->FetchField(0); 00470 $o2 = $rs->FetchField(1); 00471 $o3 = $rs->FetchField(2); 00472 if ($rs->EOF) return '<p>None found</p>'; 00473 $check = ''; 00474 $sql = ''; 00475 $s = "\n\n<table border=1 bgcolor=white><tr><td><b>".$o1->name.'</b></td><td><b>'.$o2->name.'</b></td><td><b>'.$o3->name.'</b></td></tr>'; 00476 while (!$rs->EOF) { 00477 if ($check != $rs->fields[0].'::'.$rs->fields[1]) { 00478 if ($check) { 00479 $carr = explode('::',$check); 00480 $prefix = "<a href=\"?$type=1&sql=".rawurlencode($sql).'&x#explain">'; 00481 $suffix = '</a>'; 00482 if (strlen($prefix)>2000) { 00483 $prefix = ''; 00484 $suffix = ''; 00485 } 00486 00487 $s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>'; 00488 } 00489 $sql = $rs->fields[2]; 00490 $check = $rs->fields[0].'::'.$rs->fields[1]; 00491 } else 00492 $sql .= $rs->fields[2]; 00493 if (substr($sql,strlen($sql)-1) == "\0") $sql = substr($sql,0,strlen($sql)-1); 00494 $rs->MoveNext(); 00495 } 00496 $rs->Close(); 00497 00498 $carr = explode('::',$check); 00499 $prefix = "<a target=".rand()." href=\"?&hidem=1&$type=1&sql=".rawurlencode($sql).'&x#explain">'; 00500 $suffix = '</a>'; 00501 if (strlen($prefix)>2000) { 00502 $prefix = ''; 00503 $suffix = ''; 00504 } 00505 $s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>'; 00506 00507 return $s."</table>\n\n"; 00508 } 00509 00510 // code thanks to Ixora. 00511 // http://www.ixora.com.au/scripts/query_opt.htm 00512 // requires oracle 8.1.7 or later 00513 function SuspiciousSQL($numsql=10) 00514 { 00515 $sql = " 00516 select 00517 substr(to_char(s.pct, '99.00'), 2) || '%' load, 00518 s.executions executes, 00519 p.sql_text 00520 from 00521 ( 00522 select 00523 address, 00524 buffer_gets, 00525 executions, 00526 pct, 00527 rank() over (order by buffer_gets desc) ranking 00528 from 00529 ( 00530 select 00531 address, 00532 buffer_gets, 00533 executions, 00534 100 * ratio_to_report(buffer_gets) over () pct 00535 from 00536 sys.v_\$sql 00537 where 00538 command_type != 47 and module != 'T.O.A.D.' 00539 ) 00540 where 00541 buffer_gets > 50 * executions 00542 ) s, 00543 sys.v_\$sqltext p 00544 where 00545 s.ranking <= $numsql and 00546 p.address = s.address 00547 order by 00548 1 desc, s.address, p.piece"; 00549 00550 global $ADODB_CACHE_MODE; 00551 if (isset($_GET['expsixora']) && isset($_GET['sql'])) { 00552 $partial = empty($_GET['part']); 00553 echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n"; 00554 } 00555 00556 if (isset($_GET['sql'])) return $this->_SuspiciousSQL($numsql); 00557 00558 $s = ''; 00559 $timer = time(); 00560 $s .= $this->_SuspiciousSQL($numsql); 00561 $timer = time() - $timer; 00562 00563 if ($timer > $this->noShowIxora) return $s; 00564 $s .= '<p>'; 00565 00566 $save = $ADODB_CACHE_MODE; 00567 $ADODB_CACHE_MODE = ADODB_FETCH_NUM; 00568 if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); 00569 00570 $savelog = $this->conn->LogSQL(false); 00571 $rs = $this->conn->SelectLimit($sql); 00572 $this->conn->LogSQL($savelog); 00573 00574 if (isset($savem)) $this->conn->SetFetchMode($savem); 00575 $ADODB_CACHE_MODE = $save; 00576 if ($rs) { 00577 $s .= "\n<h3>Ixora Suspicious SQL</h3>"; 00578 $s .= $this->tohtml($rs,'expsixora'); 00579 } 00580 00581 return $s; 00582 } 00583 00584 // code thanks to Ixora. 00585 // http://www.ixora.com.au/scripts/query_opt.htm 00586 // requires oracle 8.1.7 or later 00587 function ExpensiveSQL($numsql = 10) 00588 { 00589 $sql = " 00590 select 00591 substr(to_char(s.pct, '99.00'), 2) || '%' load, 00592 s.executions executes, 00593 p.sql_text 00594 from 00595 ( 00596 select 00597 address, 00598 disk_reads, 00599 executions, 00600 pct, 00601 rank() over (order by disk_reads desc) ranking 00602 from 00603 ( 00604 select 00605 address, 00606 disk_reads, 00607 executions, 00608 100 * ratio_to_report(disk_reads) over () pct 00609 from 00610 sys.v_\$sql 00611 where 00612 command_type != 47 and module != 'T.O.A.D.' 00613 ) 00614 where 00615 disk_reads > 50 * executions 00616 ) s, 00617 sys.v_\$sqltext p 00618 where 00619 s.ranking <= $numsql and 00620 p.address = s.address 00621 order by 00622 1 desc, s.address, p.piece 00623 "; 00624 global $ADODB_CACHE_MODE; 00625 if (isset($_GET['expeixora']) && isset($_GET['sql'])) { 00626 $partial = empty($_GET['part']); 00627 echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n"; 00628 } 00629 if (isset($_GET['sql'])) { 00630 $var = $this->_ExpensiveSQL($numsql); 00631 return $var; 00632 } 00633 00634 $s = ''; 00635 $timer = time(); 00636 $s .= $this->_ExpensiveSQL($numsql); 00637 $timer = time() - $timer; 00638 if ($timer > $this->noShowIxora) return $s; 00639 00640 $s .= '<p>'; 00641 $save = $ADODB_CACHE_MODE; 00642 $ADODB_CACHE_MODE = ADODB_FETCH_NUM; 00643 if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false); 00644 00645 $savelog = $this->conn->LogSQL(false); 00646 $rs = $this->conn->Execute($sql); 00647 $this->conn->LogSQL($savelog); 00648 00649 if (isset($savem)) $this->conn->SetFetchMode($savem); 00650 $ADODB_CACHE_MODE = $save; 00651 00652 if ($rs) { 00653 $s .= "\n<h3>Ixora Expensive SQL</h3>"; 00654 $s .= $this->tohtml($rs,'expeixora'); 00655 } 00656 00657 return $s; 00658 } 00659 00660 function clearsql() 00661 { 00662 $perf_table = adodb_perf::table(); 00663 // using the naive "delete from $perf_table where created<".$this->conn->sysTimeStamp will cause the table to lock, possibly 00664 // for a long time 00665 $sql = 00666 "DECLARE cnt pls_integer; 00667 BEGIN 00668 cnt := 0; 00669 FOR rec IN (SELECT ROWID AS rr FROM $perf_table WHERE created<SYSDATE) 00670 LOOP 00671 cnt := cnt + 1; 00672 DELETE FROM $perf_table WHERE ROWID=rec.rr; 00673 IF cnt = 1000 THEN 00674 COMMIT; 00675 cnt := 0; 00676 END IF; 00677 END LOOP; 00678 commit; 00679 END;"; 00680 00681 $ok = $this->conn->Execute($sql); 00682 } 00683 00684 } 00685 ?>