source: trunk/phpgwapi/inc/adodb/perf/perf-oci8.inc.php @ 2

Revision 2, 15.9 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2/*
3V4.51 29 July 2004  (c) 2000-2004 John Lim (jlim@natsoft.com.my). 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
16if (!defined('ADODB_DIR')) die();
17
18class perf_oci8 extends ADODB_perf{
19       
20        var $tablesSQL = "select segment_name as \"tablename\", sum(bytes)/1024 as \"size_in_k\",tablespace_name as \"tablespace\",count(*) \"extents\" from sys.user_extents
21           group by segment_name,tablespace_name";
22         
23        var $version;
24        var $createTableSQL = "CREATE TABLE adodb_logsql (
25                  created date NOT NULL,
26                  sql0 varchar(250) NOT NULL,
27                  sql1 varchar(4000) NOT NULL,
28                  params varchar(4000),
29                  tracer varchar(4000),
30                  timer decimal(16,6) NOT NULL
31                )";
32       
33        var $settings = array(
34        'Ratios',
35                'data cache hit ratio' => array('RATIOH',
36                        "select round((1-(phy.value / (cur.value + con.value)))*100,2)
37                        from v\$sysstat cur, v\$sysstat con, v\$sysstat phy
38                        where cur.name = 'db block gets' and
39                              con.name = 'consistent gets' and
40                              phy.name = 'physical reads'",
41                        '=WarnCacheRatio'),
42               
43                'sql cache hit ratio' => array( 'RATIOH',
44                        'select round(100*(sum(pins)-sum(reloads))/sum(pins),2)  from v$librarycache',
45                        'increase <i>shared_pool_size</i> if too ratio low'),
46                       
47                'datadict cache hit ratio' => array('RATIOH',
48                "select     
49           round((1 - (sum(getmisses) / (sum(gets) +         
50                 sum(getmisses))))*100,2)
51                from  v\$rowcache",
52                'increase <i>shared_pool_size</i> if too ratio low'),
53               
54                'memory sort ratio' => array('RATIOH',
55                "SELECT ROUND((100 * b.VALUE) /DECODE ((a.VALUE + b.VALUE),
56       0,1,(a.VALUE + b.VALUE)),2)
57FROM   v\$sysstat a,
58       v\$sysstat b
59WHERE  a.name = 'sorts (disk)'
60AND    b.name = 'sorts (memory)'",
61        "% of memory sorts compared to disk sorts - should be over 95%"),
62
63        'IO',
64                'data reads' => array('IO',
65                "select value from v\$sysstat where name='physical reads'"),
66       
67        'data writes' => array('IO',
68                "select value from v\$sysstat where name='physical writes'"),
69       
70        'Data Cache',
71                'data cache buffers' => array( 'DATAC',
72                "select a.value/b.value  from v\$parameter a, v\$parameter b
73                        where a.name = 'db_cache_size' and b.name= 'db_block_size'",
74                        'Number of cache buffers. Tune <i>db_cache_size</i> if the <i>data cache hit ratio</i> is too low.'),
75                'data cache blocksize' => array('DATAC',
76                        "select value from v\$parameter where name='db_block_size'",
77                        '' ),                   
78        'Memory Pools',
79                'data cache size' => array('DATAC',
80                        "select value from v\$parameter where name = 'db_cache_size'",
81                        'db_cache_size' ),
82                'shared pool size' => array('DATAC',
83                        "select value from v\$parameter where name = 'shared_pool_size'",
84                        'shared_pool_size, which holds shared sql, stored procedures, dict cache and similar shared structs' ),
85                'java pool size' => array('DATAJ',
86                        "select value from v\$parameter where name = 'java_pool_size'",
87                        'java_pool_size' ),
88                'large pool buffer size' => array('CACHE',
89                        "select value from v\$parameter where name='large_pool_size'",
90                        '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) ' ),
91
92                'pga buffer size' => array('CACHE',                     
93                        "select value from v\$parameter where name='pga_aggregate_target'",
94                        'program global area is private memory for sorting, and hash and bitmap merges - since oracle 9i (pga_aggregate_target)' ),
95
96               
97                'Connections',
98                'current connections' => array('SESS',
99                        'select count(*) from sys.v_$session where username is not null',
100                        ''),
101                'max connections' => array( 'SESS',
102                        "select value from v\$parameter where name='sessions'",
103                        ''),
104
105        'Memory Utilization',           
106                'data cache utilization ratio' => array('RATIOU',
107                        "select round((1-bytes/sgasize)*100, 2)
108                        from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f
109                        where name = 'free memory' and pool = 'shared pool'",
110                'Percentage of data cache actually in use - should be over 85%'),
111               
112                'shared pool utilization ratio' => array('RATIOU',
113                'select round((sga.bytes/p.value)*100,2)
114                from v$sgastat sga, v$parameter p
115                where sga.name = \'free memory\' and sga.pool = \'shared pool\'
116                and p.name = \'shared_pool_size\'',
117                'Percentage of shared pool actually used - too low is bad, too high is worse'),
118               
119                'large pool utilization ratio' => array('RATIOU',
120                        "select round((1-bytes/sgasize)*100, 2)
121                        from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f
122                        where name = 'free memory' and pool = 'large pool'",
123                'Percentage of large_pool actually in use - too low is bad, too high is worse'),
124                'sort buffer size' => array('CACHE',
125                        "select value from v\$parameter where name='sort_area_size'",
126                        'max in-mem sort_area_size (per query), uses memory in pga' ),
127
128                'pga usage at peak' => array('RATIOU',
129                '=PGA','Mb utilization at peak transactions (requires Oracle 9i+)'),
130        'Transactions',
131                'rollback segments' => array('ROLLBACK',
132                        "select count(*) from sys.v_\$rollstat",
133                        ''),
134       
135                'peak transactions' => array('ROLLBACK',
136                        "select max_utilization  tx_hwm
137                from sys.v_\$resource_limit
138                where resource_name = 'transactions'",
139                        'Taken from high-water-mark'),
140                'max transactions' => array('ROLLBACK',
141                        "select value from v\$parameter where name = 'transactions'",
142                        'max transactions / rollback segments < 3.5 (or transactions_per_rollback_segment)'),
143        'Parameters',   
144                'cursor sharing' => array('CURSOR',
145                        "select value from v\$parameter where name = 'cursor_sharing'",
146                        '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>.'),
147                /*
148                'cursor reuse' => array('CURSOR',
149                        "select count(*) from (select sql_text_wo_constants, count(*)
150  from t1
151 group by sql_text_wo_constants
152having count(*) > 100)",'These are sql statements that should be using bind variables'),*/
153                'index cache cost' => array('COST',
154                        "select value from v\$parameter where name = 'optimizer_index_caching'",
155                        '=WarnIndexCost'),
156                'random page cost' => array('COST',
157                        "select value from v\$parameter where name = 'optimizer_index_cost_adj'",
158                        '=WarnPageCost'),
159               
160                false
161               
162        );
163       
164       
165        function perf_oci8(&$conn)
166        {
167                $savelog = $conn->LogSQL(false);       
168                $this->version = $conn->ServerInfo();
169                $conn->LogSQL($savelog);       
170                $this->conn =& $conn;
171        }
172       
173        function WarnPageCost($val)
174        {
175                if ($val == 100) $s = '<font color=red><b>Too High</b>. </font>';
176                else $s = '';
177               
178                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>. ';
179        }
180       
181        function WarnIndexCost($val)
182        {
183                if ($val == 0) $s = '<font color=red><b>Too Low</b>. </font>';
184                else $s = '';
185               
186                return $s.'Percentage of indexed data blocks expected in the cache.
187                        Recommended is 20 (fast disk array) to 50 (slower hard disks). Default is 0.
188                         See <a href=http://www.dba-oracle.com/oracle_tips_cbo_part1.htm>optimizer_index_caching</a>.';
189                }
190       
191        function PGA()
192        {
193                if ($this->version['version'] < 9) return 'Oracle 9i or later required';
194               
195                $rs = $this->conn->Execute("select a.mb,a.targ as pga_size_pct,a.pct from
196           (select round(pga_target_for_estimate/1024.0/1024.0,0) Mb,
197                   pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r
198                   from v\$pga_target_advice) a left join
199           (select round(pga_target_for_estimate/1024.0/1024.0,0) Mb,
200                   pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r
201                   from v\$pga_target_advice) b on
202          a.r = b.r+1 where
203                b.pct < 100");
204                if (!$rs) return "Only in 9i or later";
205                $rs->Close();
206                if ($rs->EOF) return "PGA could be too big";
207               
208                return reset($rs->fields);
209        }
210       
211        function Explain($sql,$partial=false)
212        {
213                $savelog = $this->conn->LogSQL(false);
214                $rs =& $this->conn->SelectLimit("select ID FROM PLAN_TABLE");
215                if (!$rs) {
216                        echo "<p><b>Missing PLAN_TABLE</b></p>
217<pre>
218CREATE TABLE PLAN_TABLE (
219  STATEMENT_ID                    VARCHAR2(30),
220  TIMESTAMP                       DATE,
221  REMARKS                         VARCHAR2(80),
222  OPERATION                       VARCHAR2(30),
223  OPTIONS                         VARCHAR2(30),
224  OBJECT_NODE                     VARCHAR2(128),
225  OBJECT_OWNER                    VARCHAR2(30),
226  OBJECT_NAME                     VARCHAR2(30),
227  OBJECT_INSTANCE                 NUMBER(38),
228  OBJECT_TYPE                     VARCHAR2(30),
229  OPTIMIZER                       VARCHAR2(255),
230  SEARCH_COLUMNS                  NUMBER,
231  ID                              NUMBER(38),
232  PARENT_ID                       NUMBER(38),
233  POSITION                        NUMBER(38),
234  COST                            NUMBER(38),
235  CARDINALITY                     NUMBER(38),
236  BYTES                           NUMBER(38),
237  OTHER_TAG                       VARCHAR2(255),
238  PARTITION_START                 VARCHAR2(255),
239  PARTITION_STOP                  VARCHAR2(255),
240  PARTITION_ID                    NUMBER(38),
241  OTHER                           LONG,
242  DISTRIBUTION                    VARCHAR2(30)
243);
244</pre>";
245                        return false;
246                }
247               
248                $rs->Close();
249        //      $this->conn->debug=1;
250       
251                if ($partial) {
252                        $sqlq = $this->conn->qstr($sql.'%');
253                        $arr = $this->conn->GetArray("select distinct distinct sql1 from adodb_logsql where sql1 like $sqlq");
254                        if ($arr) {
255                                foreach($arr as $row) {
256                                        $sql = reset($row);
257                                        if (crc32($sql) == $partial) break;
258                                }
259                        }
260                }
261               
262                $s = "<p><b>Explain</b>: ".htmlspecialchars($sql)."</p>";       
263               
264                $this->conn->BeginTrans();
265                $id = "ADODB ".microtime();
266                $rs =& $this->conn->Execute("EXPLAIN PLAN SET STATEMENT_ID='$id' FOR $sql");
267                $m = $this->conn->ErrorMsg();
268                if ($m) {
269                        $this->conn->RollbackTrans();
270                        $this->conn->LogSQL($savelog);
271                        $s .= "<p>$m</p>";
272                        return $s;
273                }
274                $rs = $this->conn->Execute("
275                select
276  '<pre>'||lpad('--', (level-1)*2,'-') || trim(operation) || ' ' || trim(options)||'</pre>'  as Operation,
277  object_name,COST,CARDINALITY,bytes
278                FROM plan_table
279START WITH id = 0  and STATEMENT_ID='$id' 
280CONNECT BY prior id=parent_id and statement_id='$id'");
281               
282                $s .= rs2html($rs,false,false,false,false);
283                $this->conn->RollbackTrans();
284                $this->conn->LogSQL($savelog);
285                $s .= $this->Tracer($sql,$partial);
286                return $s;
287        }
288       
289       
290        function CheckMemory()
291        {
292                if ($this->version['version'] < 9) return 'Oracle 9i or later required';
293               
294                 $rs =& $this->conn->Execute("
295select  a.size_for_estimate as cache_mb_estimate,
296        case when a.size_factor=1 then
297                '&lt;&lt;= current'
298         when a.estd_physical_read_factor-b.estd_physical_read_factor > 0 and a.estd_physical_read_factor<1 then
299                '- BETTER - '
300        else ' ' end as currsize,
301   a.estd_physical_read_factor-b.estd_physical_read_factor as best_when_0
302   from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum  r from v\$db_cache_advice) a ,
303   (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$db_cache_advice) b where a.r = b.r-1");
304                if (!$rs) return false;
305               
306                /*
307                The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size
308                */
309                $s = "<h3>Data Cache Estimate</h3>";
310                if ($rs->EOF) {
311                        $s .= "<p>Cache that is 50% of current size is still too big</p>";
312                } else {
313                        $s .= "Ideal size of Data Cache is when \"best_when_0\" changes from a positive number and becomes zero.";
314                        $s .= rs2html($rs,false,false,false,false);
315                }
316                return $s;
317        }
318       
319        /*
320                Generate html for suspicious/expensive sql
321        */
322        function tohtml(&$rs,$type)
323        {
324                $o1 = $rs->FetchField(0);
325                $o2 = $rs->FetchField(1);
326                $o3 = $rs->FetchField(2);
327                if ($rs->EOF) return '<p>None found</p>';
328                $check = '';
329                $sql = '';
330                $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>';
331                while (!$rs->EOF) {
332                        if ($check != $rs->fields[0].'::'.$rs->fields[1]) {
333                                if ($check) {
334                                        $carr = explode('::',$check);
335                                        $prefix = "<a href=\"?$type=1&sql=".rawurlencode($sql).'&x#explain">';
336                                        $suffix = '</a>';
337                                        if (strlen($prefix)>2000) {
338                                                $prefix = '';
339                                                $suffix = '';
340                                        }
341                                       
342                                        $s .=  "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
343                                }
344                                $sql = $rs->fields[2];
345                                $check = $rs->fields[0].'::'.$rs->fields[1];                   
346                        } else
347                                $sql .= $rs->fields[2];
348                       
349                        $rs->MoveNext();
350                }
351                $rs->Close();
352               
353                $carr = explode('::',$check);
354                $prefix = "<a target=".rand()." href=\"?&hidem=1&$type=1&sql=".rawurlencode($sql).'&x#explain">';
355                $suffix = '</a>';
356                if (strlen($prefix)>2000) {
357                        $prefix = '';
358                        $suffix = '';
359                }
360                $s .=  "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
361                                       
362                return $s."</table>\n\n";
363        }
364       
365        // code thanks to Ixora.
366        // http://www.ixora.com.au/scripts/query_opt.htm
367        // requires oracle 8.1.7 or later
368        function SuspiciousSQL($numsql=10)
369        {
370                $sql = "
371select
372  substr(to_char(s.pct, '99.00'), 2) || '%'  load,
373  s.executions  executes,
374  p.sql_text
375from
376  (
377    select
378      address,
379      buffer_gets,
380      executions,
381      pct,
382      rank() over (order by buffer_gets desc)  ranking
383    from
384      (
385        select
386          address,
387          buffer_gets,
388          executions,
389          100 * ratio_to_report(buffer_gets) over ()  pct
390        from
391          sys.v_\$sql
392        where
393          command_type != 47 and module != 'T.O.A.D.'
394      )
395    where
396      buffer_gets > 50 * executions
397  )  s,
398  sys.v_\$sqltext  p
399where
400  s.ranking <= $numsql and
401  p.address = s.address
402order by
403  1 desc, s.address, p.piece";
404
405                global $ADODB_CACHE_MODE,$HTTP_GET_VARS;
406                if (isset($HTTP_GET_VARS['expsixora']) && isset($HTTP_GET_VARS['sql'])) {
407                                $partial = empty($HTTP_GET_VARS['part']);
408                                echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";
409                }
410
411                if (isset($HTTP_GET_VARS['sql'])) return $this->_SuspiciousSQL();
412               
413                $save = $ADODB_CACHE_MODE;
414                $ADODB_CACHE_MODE = ADODB_FETCH_NUM;
415                $savelog = $this->conn->LogSQL(false);
416                $rs =& $this->conn->SelectLimit($sql);
417                $this->conn->LogSQL($savelog);
418                $ADODB_CACHE_MODE = $save;
419                if ($rs) {
420                        $s = "\n<h3>Ixora Suspicious SQL</h3>";
421                        $s .= $this->tohtml($rs,'expsixora');
422                } else
423                        $s = '';
424               
425                if ($s) $s .= '<p>';
426                $s .= $this->_SuspiciousSQL();
427                return $s;
428        }
429       
430        // code thanks to Ixora.
431        // http://www.ixora.com.au/scripts/query_opt.htm
432        // requires oracle 8.1.7 or later
433        function ExpensiveSQL($numsql = 10)
434        {
435                $sql = "
436select
437  substr(to_char(s.pct, '99.00'), 2) || '%'  load,
438  s.executions  executes,
439  p.sql_text
440from
441  (
442    select
443      address,
444      disk_reads,
445      executions,
446      pct,
447      rank() over (order by disk_reads desc)  ranking
448    from
449      (
450        select
451          address,
452          disk_reads,
453          executions,
454          100 * ratio_to_report(disk_reads) over ()  pct
455        from
456          sys.v_\$sql
457        where
458          command_type != 47 and module != 'T.O.A.D.'
459      )
460    where
461      disk_reads > 50 * executions
462  )  s,
463  sys.v_\$sqltext  p
464where
465  s.ranking <= $numsql and
466  p.address = s.address
467order by
468  1 desc, s.address, p.piece
469";
470                global $ADODB_CACHE_MODE,$HTTP_GET_VARS;
471                if (isset($HTTP_GET_VARS['expeixora']) && isset($HTTP_GET_VARS['sql'])) {
472                        $partial = empty($HTTP_GET_VARS['part']);       
473                        echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";
474                }
475               
476                if (isset($HTTP_GET_VARS['sql'])) {
477                         $var =& $this->_ExpensiveSQL();
478                         return $var;
479                }
480                $save = $ADODB_CACHE_MODE;
481                $ADODB_CACHE_MODE = ADODB_FETCH_NUM;
482                $savelog = $this->conn->LogSQL(false);
483                $rs =& $this->conn->Execute($sql);
484                $this->conn->LogSQL($savelog);
485                $ADODB_CACHE_MODE = $save;
486                if ($rs) {
487                        $s = "\n<h3>Ixora Expensive SQL</h3>";
488                        $s .= $this->tohtml($rs,'expeixora');
489                } else
490                        $s = '';
491               
492               
493                if ($s) $s .= '<p>';
494                $s .= $this->_ExpensiveSQL();
495                return $s;
496        }
497       
498}
499?>
Note: See TracBrowser for help on using the repository browser.