TYPO3 CMS  TYPO3_6-2
perf-oci8.inc.php
Go to the documentation of this file.
1 <?php
2 /*
3 V5.19 23-Apr-2014 (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved.
4  Released under both BSD license and Lesser GPL library license.
5  Whenever there is any discrepancy between the two licenses,
6  the BSD license will take precedence. See License.txt.
7  Set tabs to 4 for best viewing.
8 
9  Latest version is available at http://adodb.sourceforge.net
10 
11  Library for basic performance monitoring and tuning
12 
13 */
14 
15 // security - hide paths
16 if (!defined('ADODB_DIR')) die();
17 
18 
19 class perf_oci8 extends ADODB_perf{
20 
21  var $noShowIxora = 15; // if the sql for suspicious sql is taking too long, then disable ixora
22 
23  var $tablesSQL = "select segment_name as \"tablename\", sum(bytes)/1024 as \"size_in_k\",tablespace_name as \"tablespace\",count(*) \"extents\" from sys.user_extents
24  group by segment_name,tablespace_name";
25 
26  var $version;
27 
28  var $createTableSQL = "CREATE TABLE adodb_logsql (
29  created date NOT NULL,
30  sql0 varchar(250) NOT NULL,
31  sql1 varchar(4000) NOT NULL,
32  params varchar(4000),
33  tracer varchar(4000),
34  timer decimal(16,6) NOT NULL
35  )";
36 
37  var $settings = array(
38  'Ratios',
39  'data cache hit ratio' => array('RATIOH',
40  "select round((1-(phy.value / (cur.value + con.value)))*100,2)
41  from v\$sysstat cur, v\$sysstat con, v\$sysstat phy
42  where cur.name = 'db block gets' and
43  con.name = 'consistent gets' and
44  phy.name = 'physical reads'",
45  '=WarnCacheRatio'),
46 
47  'sql cache hit ratio' => array( 'RATIOH',
48  'select round(100*(sum(pins)-sum(reloads))/sum(pins),2) from v$librarycache',
49  'increase <i>shared_pool_size</i> if too ratio low'),
50 
51  'datadict cache hit ratio' => array('RATIOH',
52  "select
53  round((1 - (sum(getmisses) / (sum(gets) +
54  sum(getmisses))))*100,2)
55  from v\$rowcache",
56  'increase <i>shared_pool_size</i> if too ratio low'),
57 
58  'memory sort ratio' => array('RATIOH',
59  "SELECT ROUND((100 * b.VALUE) /DECODE ((a.VALUE + b.VALUE),
60  0,1,(a.VALUE + b.VALUE)),2)
61 FROM v\$sysstat a,
62  v\$sysstat b
63 WHERE a.name = 'sorts (disk)'
64 AND b.name = 'sorts (memory)'",
65  "% of memory sorts compared to disk sorts - should be over 95%"),
66 
67  'IO',
68  'data reads' => array('IO',
69  "select value from v\$sysstat where name='physical reads'"),
70 
71  'data writes' => array('IO',
72  "select value from v\$sysstat where name='physical writes'"),
73 
74  'Data Cache',
75 
76  'data cache buffers' => array( 'DATAC',
77  "select a.value/b.value from v\$parameter a, v\$parameter b
78  where a.name = 'db_cache_size' and b.name= 'db_block_size'",
79  'Number of cache buffers. Tune <i>db_cache_size</i> if the <i>data cache hit ratio</i> is too low.'),
80  'data cache blocksize' => array('DATAC',
81  "select value from v\$parameter where name='db_block_size'",
82  '' ),
83 
84  'Memory Pools',
85  'Mem Max Target (11g+)' => array( 'DATAC',
86  "select value from v\$parameter where name = 'memory_max_target'",
87  'The memory_max_size is the maximum value to which memory_target can be set.' ),
88  'Memory target (11g+)' => array( 'DATAC',
89  "select value from v\$parameter where name = 'memory_target'",
90  'If memory_target is defined then SGA and PGA targets are consolidated into one memory_target.' ),
91  'SGA Max Size' => array( 'DATAC',
92  "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'sga_max_size'",
93  'The sga_max_size is the maximum value to which sga_target can be set.' ),
94  'SGA target' => array( 'DATAC',
95  "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'sga_target'",
96  '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.' ),
97  'PGA aggr target' => array( 'DATAC',
98  "select nvl(value,0)/1024.0/1024 || 'M' from v\$parameter where name = 'pga_aggregate_target'",
99  '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.' ),
100  'data cache size' => array('DATAC',
101  "select value from v\$parameter where name = 'db_cache_size'",
102  'db_cache_size' ),
103  'shared pool size' => array('DATAC',
104  "select value from v\$parameter where name = 'shared_pool_size'",
105  'shared_pool_size, which holds shared sql, stored procedures, dict cache and similar shared structs' ),
106  'java pool size' => array('DATAJ',
107  "select value from v\$parameter where name = 'java_pool_size'",
108  'java_pool_size' ),
109  'large pool buffer size' => array('CACHE',
110  "select value from v\$parameter where name='large_pool_size'",
111  '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) ' ),
112 
113  'dynamic memory usage' => array('CACHE', "select '-' from dual", '=DynMemoryUsage'),
114 
115  'Connections',
116  'current connections' => array('SESS',
117  'select count(*) from sys.v_$session where username is not null',
118  ''),
119  'max connections' => array( 'SESS',
120  "select value from v\$parameter where name='sessions'",
121  ''),
122 
123  'Memory Utilization',
124  'data cache utilization ratio' => array('RATIOU',
125  "select round((1-bytes/sgasize)*100, 2)
126  from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f
127  where name = 'free memory' and pool = 'shared pool'",
128  'Percentage of data cache actually in use - should be over 85%'),
129 
130  'shared pool utilization ratio' => array('RATIOU',
131  'select round((sga.bytes/case when p.value=0 then sga.bytes else to_number(p.value) end)*100,2)
132  from v$sgastat sga, v$parameter p
133  where sga.name = \'free memory\' and sga.pool = \'shared pool\'
134  and p.name = \'shared_pool_size\'',
135  'Percentage of shared pool actually used - too low is bad, too high is worse'),
136 
137  'large pool utilization ratio' => array('RATIOU',
138  "select round((1-bytes/sgasize)*100, 2)
139  from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f
140  where name = 'free memory' and pool = 'large pool'",
141  'Percentage of large_pool actually in use - too low is bad, too high is worse'),
142  'sort buffer size' => array('CACHE',
143  "select value from v\$parameter where name='sort_area_size'",
144  'max in-mem sort_area_size (per query), uses memory in pga' ),
145 
146  /*'pga usage at peak' => array('RATIOU',
147  '=PGA','Mb utilization at peak transactions (requires Oracle 9i+)'),*/
148  'Transactions',
149  'rollback segments' => array('ROLLBACK',
150  "select count(*) from sys.v_\$rollstat",
151  ''),
152 
153  'peak transactions' => array('ROLLBACK',
154  "select max_utilization tx_hwm
155  from sys.v_\$resource_limit
156  where resource_name = 'transactions'",
157  'Taken from high-water-mark'),
158  'max transactions' => array('ROLLBACK',
159  "select value from v\$parameter where name = 'transactions'",
160  'max transactions / rollback segments < 3.5 (or transactions_per_rollback_segment)'),
161  'Parameters',
162  'cursor sharing' => array('CURSOR',
163  "select value from v\$parameter where name = 'cursor_sharing'",
164  '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>.'),
165  /*
166  'cursor reuse' => array('CURSOR',
167  "select count(*) from (select sql_text_wo_constants, count(*)
168  from t1
169  group by sql_text_wo_constants
170 having count(*) > 100)",'These are sql statements that should be using bind variables'),*/
171  'index cache cost' => array('COST',
172  "select value from v\$parameter where name = 'optimizer_index_caching'",
173  '=WarnIndexCost'),
174  'random page cost' => array('COST',
175  "select value from v\$parameter where name = 'optimizer_index_cost_adj'",
176  '=WarnPageCost'),
177  'Waits',
178  'Recent wait events' => array('WAITS','select \'Top 5 events\' from dual','=TopRecentWaits'),
179 // 'Historical wait SQL' => array('WAITS','select \'Last 2 days\' from dual','=TopHistoricalWaits'), -- requires AWR license
180  'Backup',
181  'Achivelog Mode' => array('BACKUP', 'select log_mode from v$database', '=LogMode'),
182 
183  'DBID' => array('BACKUP','select dbid from v$database','Primary key of database, used for recovery with an RMAN Recovery Catalog'),
184  'Archive Log Dest' => array('BACKUP', "SELECT NVL(v1.value,v2.value)
185 FROM v\$parameter v1, v\$parameter v2 WHERE v1.name='log_archive_dest' AND v2.name='log_archive_dest_10'", ''),
186 
187  '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.'),
188 
189  'Flashback Usage' => array('BACKUP', "select nvl('-','Flashback Area not used') from v\$parameter where name=lower('DB_RECOVERY_FILE_DEST')", '=FlashUsage', 'Flashback area usage.'),
190 
191  '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.'),
192  'Recent RMAN Jobs' => array('BACKUP', "select '-' from dual", "=RMAN"),
193 
194  // '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.'),
195  'Storage', 'Tablespaces' => array('TABLESPACE', "select '-' from dual", "=TableSpace"),
196  false
197 
198  );
199 
200 
201  function perf_oci8(&$conn)
202  {
203  global $gSQLBlockRows;
204 
205  $gSQLBlockRows = 1000;
206  $savelog = $conn->LogSQL(false);
207  $this->version = $conn->ServerInfo();
208  $conn->LogSQL($savelog);
209  $this->conn = $conn;
210  }
211 
212  function LogMode()
213  {
214  $mode = $this->conn->GetOne("select log_mode from v\$database");
215 
216  if ($mode == 'ARCHIVELOG') return 'To turn off archivelog:<br>
217  <pre><font size=-2>
218  SQLPLUS> connect sys as sysdba;
219  SQLPLUS> shutdown immediate;
220 
221  SQLPLUS> startup mount exclusive;
222  SQLPLUS> alter database noarchivelog;
223  SQLPLUS> alter database open;
224 </font></pre>';
225 
226  return 'To turn on archivelog:<br>
227  <pre><font size=-2>
228  SQLPLUS> connect sys as sysdba;
229  SQLPLUS> shutdown immediate;
230 
231  SQLPLUS> startup mount exclusive;
232  SQLPLUS> alter database archivelog;
233  SQLPLUS> archive log start;
234  SQLPLUS> alter database open;
235 </font></pre>';
236  }
237 
238  function TopRecentWaits()
239  {
240 
241  $rs = $this->conn->Execute("select * from (
242  select event, round(100*time_waited/(select sum(time_waited) from v\$system_event where wait_class <> 'Idle'),1) \"% Wait\",
243  total_waits,time_waited, average_wait,wait_class from v\$system_event where wait_class <> 'Idle' order by 2 desc
244  ) where rownum <=5");
245 
246  $ret = rs2html($rs,false,false,false,false);
247  return "&nbsp;<p>".$ret."&nbsp;</p>";
248 
249  }
250 
252  {
253  $days = 2;
254 
255  $rs = $this->conn->Execute("select * from ( SELECT
256  b.wait_class,B.NAME,
257  round(sum(wait_time+TIME_WAITED)/1000000) waitsecs,
258  parsing_schema_name,
259  C.SQL_TEXT, a.sql_id
260 FROM V\$ACTIVE_SESSION_HISTORY A
261  join V\$EVENT_NAME B on A.EVENT# = B.EVENT#
262  join V\$SQLAREA C on A.SQL_ID = C.SQL_ID
263 WHERE A.SAMPLE_TIME BETWEEN sysdate-$days and sysdate
264  and parsing_schema_name not in ('SYS','SYSMAN','DBSNMP','SYSTEM')
265 GROUP BY b.wait_class,parsing_schema_name,C.SQL_TEXT, B.NAME,A.sql_id
266 order by 3 desc) where rownum <=10");
267 
268  $ret = rs2html($rs,false,false,false,false);
269  return "&nbsp;<p>".$ret."&nbsp;</p>";
270 
271  }
272 
273  function TableSpace()
274  {
275 
276  $rs = $this->conn->Execute(
277  "select tablespace_name,round(sum(bytes)/1024/1024) as Used_MB,round(sum(maxbytes)/1024/1024) as Max_MB, round(sum(bytes)/sum(maxbytes),4) * 100 as PCT
278  from dba_data_files
279  group by tablespace_name order by 2 desc");
280 
281  $ret = "<p><b>Tablespace</b>".rs2html($rs,false,false,false,false);
282 
283  $rs = $this->conn->Execute("select * from dba_data_files order by tablespace_name, 1");
284  $ret .= "<p><b>Datafile</b>".rs2html($rs,false,false,false,false);
285 
286  return "&nbsp;<p>".$ret."&nbsp;</p>";
287  }
288 
289  function RMAN()
290  {
291  $rs = $this->conn->Execute("select * from (select start_time, end_time, operation, status, mbytes_processed, output_device_type
292  from V\$RMAN_STATUS order by start_time desc) where rownum <=10");
293 
294  $ret = rs2html($rs,false,false,false,false);
295  return "&nbsp;<p>".$ret."&nbsp;</p>";
296 
297  }
298 
299  function DynMemoryUsage()
300  {
301  if (@$this->version['version'] >= 11) {
302  $rs = $this->conn->Execute("select component, current_size/1024./1024 as \"CurrSize (M)\" from V\$MEMORY_DYNAMIC_COMPONENTS");
303 
304  } else
305  $rs = $this->conn->Execute("select name, round(bytes/1024./1024,2) as \"CurrSize (M)\" from V\$sgainfo");
306 
307 
308  $ret = rs2html($rs,false,false,false,false);
309  return "&nbsp;<p>".$ret."&nbsp;</p>";
310  }
311 
312  function FlashUsage()
313  {
314  $rs = $this->conn->Execute("select * from V\$FLASH_RECOVERY_AREA_USAGE");
315  $ret = rs2html($rs,false,false,false,false);
316  return "&nbsp;<p>".$ret."&nbsp;</p>";
317  }
318 
319  function WarnPageCost($val)
320  {
321  if ($val == 100 && $this->version['version'] < 10) $s = '<font color=red><b>Too High</b>. </font>';
322  else $s = '';
323 
324  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>. ';
325  }
326 
327  function WarnIndexCost($val)
328  {
329  if ($val == 0 && $this->version['version'] < 10) $s = '<font color=red><b>Too Low</b>. </font>';
330  else $s = '';
331 
332  return $s.'Percentage of indexed data blocks expected in the cache.
333  Recommended is 20 (fast disk array) to 30 (slower hard disks). Default is 0.
334  See <a href=http://www.dba-oracle.com/oracle_tips_cbo_part1.htm>optimizer_index_caching</a>.';
335  }
336 
337  function PGA()
338  {
339 
340  //if ($this->version['version'] < 9) return 'Oracle 9i or later required';
341  }
342 
343  function PGA_Advice()
344  {
345  $t = "<h3>PGA Advice Estimate</h3>";
346  if ($this->version['version'] < 9) return $t.'Oracle 9i or later required';
347 
348  $rs = $this->conn->Execute('select a.MB,
349  case when a.targ = 1 then \'<<= Current \'
350  when a.targ < 1 or a.pct <= b.pct then null
351  else
352  \'- BETTER than Current by \'||round(a.pct/b.pct*100-100,2)||\'%\' end as "Percent Improved",
353  a.targ as "PGA Size Factor",a.pct "% Perf"
354  from
355  (select round(pga_target_for_estimate/1024.0/1024.0,0) MB,
356  pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r
357  from v$pga_target_advice) a left join
358  (select round(pga_target_for_estimate/1024.0/1024.0,0) MB,
359  pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r
360  from v$pga_target_advice) b on
361  a.r = b.r+1 where
362  b.pct < 100');
363  if (!$rs) return $t."Only in 9i or later";
364  // $rs->Close();
365  if ($rs->EOF) return $t."PGA could be too big";
366 
367  return $t.rs2html($rs,false,false,true,false);
368  }
369 
370  function Explain($sql,$partial=false)
371  {
372  $savelog = $this->conn->LogSQL(false);
373  $rs = $this->conn->SelectLimit("select ID FROM PLAN_TABLE");
374  if (!$rs) {
375  echo "<p><b>Missing PLAN_TABLE</b></p>
376 <pre>
377 CREATE TABLE PLAN_TABLE (
378  STATEMENT_ID VARCHAR2(30),
379  TIMESTAMP DATE,
380  REMARKS VARCHAR2(80),
381  OPERATION VARCHAR2(30),
382  OPTIONS VARCHAR2(30),
383  OBJECT_NODE VARCHAR2(128),
384  OBJECT_OWNER VARCHAR2(30),
385  OBJECT_NAME VARCHAR2(30),
386  OBJECT_INSTANCE NUMBER(38),
387  OBJECT_TYPE VARCHAR2(30),
388  OPTIMIZER VARCHAR2(255),
389  SEARCH_COLUMNS NUMBER,
390  ID NUMBER(38),
391  PARENT_ID NUMBER(38),
392  POSITION NUMBER(38),
393  COST NUMBER(38),
394  CARDINALITY NUMBER(38),
395  BYTES NUMBER(38),
396  OTHER_TAG VARCHAR2(255),
397  PARTITION_START VARCHAR2(255),
398  PARTITION_STOP VARCHAR2(255),
399  PARTITION_ID NUMBER(38),
400  OTHER LONG,
401  DISTRIBUTION VARCHAR2(30)
402 );
403 </pre>";
404  return false;
405  }
406 
407  $rs->Close();
408  // $this->conn->debug=1;
409 
410  if ($partial) {
411  $sqlq = $this->conn->qstr($sql.'%');
412  $arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");
413  if ($arr) {
414  foreach($arr as $row) {
415  $sql = reset($row);
416  if (crc32($sql) == $partial) break;
417  }
418  }
419  }
420 
421  $s = "<p><b>Explain</b>: ".htmlspecialchars($sql)."</p>";
422 
423  $this->conn->BeginTrans();
424  $id = "ADODB ".microtime();
425 
426  $rs = $this->conn->Execute("EXPLAIN PLAN SET STATEMENT_ID='$id' FOR $sql");
427  $m = $this->conn->ErrorMsg();
428  if ($m) {
429  $this->conn->RollbackTrans();
430  $this->conn->LogSQL($savelog);
431  $s .= "<p>$m</p>";
432  return $s;
433  }
434  $rs = $this->conn->Execute("
435  select
436  '<pre>'||lpad('--', (level-1)*2,'-') || trim(operation) || ' ' || trim(options)||'</pre>' as Operation,
437  object_name,COST,CARDINALITY,bytes
438  FROM plan_table
439 START WITH id = 0 and STATEMENT_ID='$id'
440 CONNECT BY prior id=parent_id and statement_id='$id'");
441 
442  $s .= rs2html($rs,false,false,false,false);
443  $this->conn->RollbackTrans();
444  $this->conn->LogSQL($savelog);
445  $s .= $this->Tracer($sql,$partial);
446  return $s;
447  }
448 
449  function CheckMemory()
450  {
451  if ($this->version['version'] < 9) return 'Oracle 9i or later required';
452 
453  $rs = $this->conn->Execute("
454 select a.name Buffer_Pool, b.size_for_estimate as cache_mb_estimate,
455  case when b.size_factor=1 then
456  '&lt;&lt;= Current'
457  when a.estd_physical_read_factor-b.estd_physical_read_factor > 0.001 and b.estd_physical_read_factor<1 then
458  '- BETTER than current by ' || round((1-b.estd_physical_read_factor)/b.estd_physical_read_factor*100,2) || '%'
459  else ' ' end as RATING,
460  b.estd_physical_read_factor \"Phys. Reads Factor\",
461  round((a.estd_physical_read_factor-b.estd_physical_read_factor)/b.estd_physical_read_factor*100,2) as \"% Improve\"
462  from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r,name from v\$db_cache_advice order by name,1) a ,
463  (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r,name from v\$db_cache_advice order by name,1) b
464  where a.r = b.r-1 and a.name = b.name
465  ");
466  if (!$rs) return false;
467 
468  /*
469  The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size
470  */
471  $s = "<h3>Data Cache Advice Estimate</h3>";
472  if ($rs->EOF) {
473  $s .= "<p>Cache that is 50% of current size is still too big</p>";
474  } else {
475  $s .= "Ideal size of Data Cache is when %BETTER gets close to zero.";
476  $s .= rs2html($rs,false,false,false,false);
477  }
478  return $s.$this->PGA_Advice();
479  }
480 
481  /*
482  Generate html for suspicious/expensive sql
483  */
484  function tohtml(&$rs,$type)
485  {
486  $o1 = $rs->FetchField(0);
487  $o2 = $rs->FetchField(1);
488  $o3 = $rs->FetchField(2);
489  if ($rs->EOF) return '<p>None found</p>';
490  $check = '';
491  $sql = '';
492  $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>';
493  while (!$rs->EOF) {
494  if ($check != $rs->fields[0].'::'.$rs->fields[1]) {
495  if ($check) {
496  $carr = explode('::',$check);
497  $prefix = "<a href=\"?$type=1&sql=".rawurlencode($sql).'&x#explain">';
498  $suffix = '</a>';
499  if (strlen($prefix)>2000) {
500  $prefix = '';
501  $suffix = '';
502  }
503 
504  $s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
505  }
506  $sql = $rs->fields[2];
507  $check = $rs->fields[0].'::'.$rs->fields[1];
508  } else
509  $sql .= $rs->fields[2];
510  if (substr($sql,strlen($sql)-1) == "\0") $sql = substr($sql,0,strlen($sql)-1);
511  $rs->MoveNext();
512  }
513  $rs->Close();
514 
515  $carr = explode('::',$check);
516  $prefix = "<a target=".rand()." href=\"?&hidem=1&$type=1&sql=".rawurlencode($sql).'&x#explain">';
517  $suffix = '</a>';
518  if (strlen($prefix)>2000) {
519  $prefix = '';
520  $suffix = '';
521  }
522  $s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
523 
524  return $s."</table>\n\n";
525  }
526 
527  // code thanks to Ixora.
528  // http://www.ixora.com.au/scripts/query_opt.htm
529  // requires oracle 8.1.7 or later
530  function SuspiciousSQL($numsql=10)
531  {
532  $sql = "
533 select
534  substr(to_char(s.pct, '99.00'), 2) || '%' load,
535  s.executions executes,
536  p.sql_text
537 from
538  (
539  select
540  address,
541  buffer_gets,
542  executions,
543  pct,
544  rank() over (order by buffer_gets desc) ranking
545  from
546  (
547  select
548  address,
549  buffer_gets,
550  executions,
551  100 * ratio_to_report(buffer_gets) over () pct
552  from
553  sys.v_\$sql
554  where
555  command_type != 47 and module != 'T.O.A.D.'
556  )
557  where
558  buffer_gets > 50 * executions
559  ) s,
560  sys.v_\$sqltext p
561 where
562  s.ranking <= $numsql and
563  p.address = s.address
564 order by
565  1 desc, s.address, p.piece";
566 
567  global $ADODB_CACHE_MODE;
568  if (isset($_GET['expsixora']) && isset($_GET['sql'])) {
569  $partial = empty($_GET['part']);
570  echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
571  }
572 
573  if (isset($_GET['sql'])) return $this->_SuspiciousSQL($numsql);
574 
575  $s = '';
576  $timer = time();
577  $s .= $this->_SuspiciousSQL($numsql);
578  $timer = time() - $timer;
579 
580  if ($timer > $this->noShowIxora) return $s;
581  $s .= '<p>';
582 
583  $save = $ADODB_CACHE_MODE;
584  $ADODB_CACHE_MODE = ADODB_FETCH_NUM;
585  if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
586 
587  $savelog = $this->conn->LogSQL(false);
588  $rs = $this->conn->SelectLimit($sql);
589  $this->conn->LogSQL($savelog);
590 
591  if (isset($savem)) $this->conn->SetFetchMode($savem);
592  $ADODB_CACHE_MODE = $save;
593  if ($rs) {
594  $s .= "\n<h3>Ixora Suspicious SQL</h3>";
595  $s .= $this->tohtml($rs,'expsixora');
596  }
597 
598  return $s;
599  }
600 
601  // code thanks to Ixora.
602  // http://www.ixora.com.au/scripts/query_opt.htm
603  // requires oracle 8.1.7 or later
604  function ExpensiveSQL($numsql = 10)
605  {
606  $sql = "
607 select
608  substr(to_char(s.pct, '99.00'), 2) || '%' load,
609  s.executions executes,
610  p.sql_text
611 from
612  (
613  select
614  address,
615  disk_reads,
616  executions,
617  pct,
618  rank() over (order by disk_reads desc) ranking
619  from
620  (
621  select
622  address,
623  disk_reads,
624  executions,
625  100 * ratio_to_report(disk_reads) over () pct
626  from
627  sys.v_\$sql
628  where
629  command_type != 47 and module != 'T.O.A.D.'
630  )
631  where
632  disk_reads > 50 * executions
633  ) s,
634  sys.v_\$sqltext p
635 where
636  s.ranking <= $numsql and
637  p.address = s.address
638 order by
639  1 desc, s.address, p.piece
640 ";
641  global $ADODB_CACHE_MODE;
642  if (isset($_GET['expeixora']) && isset($_GET['sql'])) {
643  $partial = empty($_GET['part']);
644  echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
645  }
646  if (isset($_GET['sql'])) {
647  $var = $this->_ExpensiveSQL($numsql);
648  return $var;
649  }
650 
651  $s = '';
652  $timer = time();
653  $s .= $this->_ExpensiveSQL($numsql);
654  $timer = time() - $timer;
655  if ($timer > $this->noShowIxora) return $s;
656 
657  $s .= '<p>';
658  $save = $ADODB_CACHE_MODE;
659  $ADODB_CACHE_MODE = ADODB_FETCH_NUM;
660  if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
661 
662  $savelog = $this->conn->LogSQL(false);
663  $rs = $this->conn->Execute($sql);
664  $this->conn->LogSQL($savelog);
665 
666  if (isset($savem)) $this->conn->SetFetchMode($savem);
667  $ADODB_CACHE_MODE = $save;
668 
669  if ($rs) {
670  $s .= "\n<h3>Ixora Expensive SQL</h3>";
671  $s .= $this->tohtml($rs,'expeixora');
672  }
673 
674  return $s;
675  }
676 
677  function clearsql()
678  {
679  $perf_table = adodb_perf::table();
680  // using the naive "delete from $perf_table where created<".$this->conn->sysTimeStamp will cause the table to lock, possibly
681  // for a long time
682  $sql =
683 "DECLARE cnt pls_integer;
684 BEGIN
685  cnt := 0;
686  FOR rec IN (SELECT ROWID AS rr FROM $perf_table WHERE created<SYSDATE)
687  LOOP
688  cnt := cnt + 1;
689  DELETE FROM $perf_table WHERE ROWID=rec.rr;
690  IF cnt = 1000 THEN
691  COMMIT;
692  cnt := 0;
693  END IF;
694  END LOOP;
695  commit;
696 END;";
697 
698  $ok = $this->conn->Execute($sql);
699  }
700 
701 }
ExpensiveSQL($numsql=10)
Explain($sql, $partial=false)
$sql
Definition: server.php:82
perf_oci8(&$conn)
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:92
static table($newtable=false)
GLOBAL $gSQLBlockRows
Definition: tohtml.inc.php:12
$conn
Definition: server.php:79
die
Definition: index.php:6
rs2html(&$rs, $ztabhtml=false, $zheaderarray=false, $htmlspecialchars=true, $echo=true)
Definition: tohtml.inc.php:41
tohtml(&$rs, $type)
SuspiciousSQL($numsql=10)
WarnIndexCost($val)
WarnPageCost($val)