36 |
kaklik |
1 |
<?php
|
|
|
2 |
/*
|
|
|
3 |
V4.80 8 Mar 2006 (c) 2000-2006 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
|
|
|
16 |
if (!defined('ADODB_DIR')) die();
|
|
|
17 |
|
|
|
18 |
class 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)
|
|
|
57 |
FROM v\$sysstat a,
|
|
|
58 |
v\$sysstat b
|
|
|
59 |
WHERE a.name = 'sorts (disk)'
|
|
|
60 |
AND 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
|
|
|
152 |
having 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>
|
|
|
218 |
CREATE 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 |
|
|
|
267 |
$rs =& $this->conn->Execute("EXPLAIN PLAN SET STATEMENT_ID='$id' FOR $sql");
|
|
|
268 |
$m = $this->conn->ErrorMsg();
|
|
|
269 |
if ($m) {
|
|
|
270 |
$this->conn->RollbackTrans();
|
|
|
271 |
$this->conn->LogSQL($savelog);
|
|
|
272 |
$s .= "<p>$m</p>";
|
|
|
273 |
return $s;
|
|
|
274 |
}
|
|
|
275 |
$rs =& $this->conn->Execute("
|
|
|
276 |
select
|
|
|
277 |
'<pre>'||lpad('--', (level-1)*2,'-') || trim(operation) || ' ' || trim(options)||'</pre>' as Operation,
|
|
|
278 |
object_name,COST,CARDINALITY,bytes
|
|
|
279 |
FROM plan_table
|
|
|
280 |
START WITH id = 0 and STATEMENT_ID='$id'
|
|
|
281 |
CONNECT BY prior id=parent_id and statement_id='$id'");
|
|
|
282 |
|
|
|
283 |
$s .= rs2html($rs,false,false,false,false);
|
|
|
284 |
$this->conn->RollbackTrans();
|
|
|
285 |
$this->conn->LogSQL($savelog);
|
|
|
286 |
$s .= $this->Tracer($sql,$partial);
|
|
|
287 |
return $s;
|
|
|
288 |
}
|
|
|
289 |
|
|
|
290 |
|
|
|
291 |
function CheckMemory()
|
|
|
292 |
{
|
|
|
293 |
if ($this->version['version'] < 9) return 'Oracle 9i or later required';
|
|
|
294 |
|
|
|
295 |
$rs =& $this->conn->Execute("
|
|
|
296 |
select a.size_for_estimate as cache_mb_estimate,
|
|
|
297 |
case when a.size_factor=1 then
|
|
|
298 |
'<<= current'
|
|
|
299 |
when a.estd_physical_read_factor-b.estd_physical_read_factor > 0 and a.estd_physical_read_factor<1 then
|
|
|
300 |
'- BETTER - '
|
|
|
301 |
else ' ' end as currsize,
|
|
|
302 |
a.estd_physical_read_factor-b.estd_physical_read_factor as best_when_0
|
|
|
303 |
from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$db_cache_advice) a ,
|
|
|
304 |
(select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$db_cache_advice) b where a.r = b.r-1");
|
|
|
305 |
if (!$rs) return false;
|
|
|
306 |
|
|
|
307 |
/*
|
|
|
308 |
The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size
|
|
|
309 |
*/
|
|
|
310 |
$s = "<h3>Data Cache Estimate</h3>";
|
|
|
311 |
if ($rs->EOF) {
|
|
|
312 |
$s .= "<p>Cache that is 50% of current size is still too big</p>";
|
|
|
313 |
} else {
|
|
|
314 |
$s .= "Ideal size of Data Cache is when \"best_when_0\" changes from a positive number and becomes zero.";
|
|
|
315 |
$s .= rs2html($rs,false,false,false,false);
|
|
|
316 |
}
|
|
|
317 |
return $s;
|
|
|
318 |
}
|
|
|
319 |
|
|
|
320 |
/*
|
|
|
321 |
Generate html for suspicious/expensive sql
|
|
|
322 |
*/
|
|
|
323 |
function tohtml(&$rs,$type)
|
|
|
324 |
{
|
|
|
325 |
$o1 = $rs->FetchField(0);
|
|
|
326 |
$o2 = $rs->FetchField(1);
|
|
|
327 |
$o3 = $rs->FetchField(2);
|
|
|
328 |
if ($rs->EOF) return '<p>None found</p>';
|
|
|
329 |
$check = '';
|
|
|
330 |
$sql = '';
|
|
|
331 |
$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>';
|
|
|
332 |
while (!$rs->EOF) {
|
|
|
333 |
if ($check != $rs->fields[0].'::'.$rs->fields[1]) {
|
|
|
334 |
if ($check) {
|
|
|
335 |
$carr = explode('::',$check);
|
|
|
336 |
$prefix = "<a href=\"?$type=1&sql=".rawurlencode($sql).'&x#explain">';
|
|
|
337 |
$suffix = '</a>';
|
|
|
338 |
if (strlen($prefix)>2000) {
|
|
|
339 |
$prefix = '';
|
|
|
340 |
$suffix = '';
|
|
|
341 |
}
|
|
|
342 |
|
|
|
343 |
$s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
|
|
|
344 |
}
|
|
|
345 |
$sql = $rs->fields[2];
|
|
|
346 |
$check = $rs->fields[0].'::'.$rs->fields[1];
|
|
|
347 |
} else
|
|
|
348 |
$sql .= $rs->fields[2];
|
|
|
349 |
if (substr($sql,strlen($sql)-1) == "\0") $sql = substr($sql,0,strlen($sql)-1);
|
|
|
350 |
$rs->MoveNext();
|
|
|
351 |
}
|
|
|
352 |
$rs->Close();
|
|
|
353 |
|
|
|
354 |
$carr = explode('::',$check);
|
|
|
355 |
$prefix = "<a target=".rand()." href=\"?&hidem=1&$type=1&sql=".rawurlencode($sql).'&x#explain">';
|
|
|
356 |
$suffix = '</a>';
|
|
|
357 |
if (strlen($prefix)>2000) {
|
|
|
358 |
$prefix = '';
|
|
|
359 |
$suffix = '';
|
|
|
360 |
}
|
|
|
361 |
$s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
|
|
|
362 |
|
|
|
363 |
return $s."</table>\n\n";
|
|
|
364 |
}
|
|
|
365 |
|
|
|
366 |
// code thanks to Ixora.
|
|
|
367 |
// http://www.ixora.com.au/scripts/query_opt.htm
|
|
|
368 |
// requires oracle 8.1.7 or later
|
|
|
369 |
function SuspiciousSQL($numsql=10)
|
|
|
370 |
{
|
|
|
371 |
$sql = "
|
|
|
372 |
select
|
|
|
373 |
substr(to_char(s.pct, '99.00'), 2) || '%' load,
|
|
|
374 |
s.executions executes,
|
|
|
375 |
p.sql_text
|
|
|
376 |
from
|
|
|
377 |
(
|
|
|
378 |
select
|
|
|
379 |
address,
|
|
|
380 |
buffer_gets,
|
|
|
381 |
executions,
|
|
|
382 |
pct,
|
|
|
383 |
rank() over (order by buffer_gets desc) ranking
|
|
|
384 |
from
|
|
|
385 |
(
|
|
|
386 |
select
|
|
|
387 |
address,
|
|
|
388 |
buffer_gets,
|
|
|
389 |
executions,
|
|
|
390 |
100 * ratio_to_report(buffer_gets) over () pct
|
|
|
391 |
from
|
|
|
392 |
sys.v_\$sql
|
|
|
393 |
where
|
|
|
394 |
command_type != 47 and module != 'T.O.A.D.'
|
|
|
395 |
)
|
|
|
396 |
where
|
|
|
397 |
buffer_gets > 50 * executions
|
|
|
398 |
) s,
|
|
|
399 |
sys.v_\$sqltext p
|
|
|
400 |
where
|
|
|
401 |
s.ranking <= $numsql and
|
|
|
402 |
p.address = s.address
|
|
|
403 |
order by
|
|
|
404 |
1 desc, s.address, p.piece";
|
|
|
405 |
|
|
|
406 |
global $ADODB_CACHE_MODE;
|
|
|
407 |
if (isset($_GET['expsixora']) && isset($_GET['sql'])) {
|
|
|
408 |
$partial = empty($_GET['part']);
|
|
|
409 |
echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
|
|
|
410 |
}
|
|
|
411 |
|
|
|
412 |
if (isset($_GET['sql'])) return $this->_SuspiciousSQL($numsql);
|
|
|
413 |
|
|
|
414 |
$s = '';
|
|
|
415 |
$s .= $this->_SuspiciousSQL($numsql);
|
|
|
416 |
$s .= '<p>';
|
|
|
417 |
|
|
|
418 |
$save = $ADODB_CACHE_MODE;
|
|
|
419 |
$ADODB_CACHE_MODE = ADODB_FETCH_NUM;
|
|
|
420 |
if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
|
|
|
421 |
|
|
|
422 |
$savelog = $this->conn->LogSQL(false);
|
|
|
423 |
$rs =& $this->conn->SelectLimit($sql);
|
|
|
424 |
$this->conn->LogSQL($savelog);
|
|
|
425 |
|
|
|
426 |
if (isset($savem)) $this->conn->SetFetchMode($savem);
|
|
|
427 |
$ADODB_CACHE_MODE = $save;
|
|
|
428 |
if ($rs) {
|
|
|
429 |
$s .= "\n<h3>Ixora Suspicious SQL</h3>";
|
|
|
430 |
$s .= $this->tohtml($rs,'expsixora');
|
|
|
431 |
}
|
|
|
432 |
|
|
|
433 |
return $s;
|
|
|
434 |
}
|
|
|
435 |
|
|
|
436 |
// code thanks to Ixora.
|
|
|
437 |
// http://www.ixora.com.au/scripts/query_opt.htm
|
|
|
438 |
// requires oracle 8.1.7 or later
|
|
|
439 |
function ExpensiveSQL($numsql = 10)
|
|
|
440 |
{
|
|
|
441 |
$sql = "
|
|
|
442 |
select
|
|
|
443 |
substr(to_char(s.pct, '99.00'), 2) || '%' load,
|
|
|
444 |
s.executions executes,
|
|
|
445 |
p.sql_text
|
|
|
446 |
from
|
|
|
447 |
(
|
|
|
448 |
select
|
|
|
449 |
address,
|
|
|
450 |
disk_reads,
|
|
|
451 |
executions,
|
|
|
452 |
pct,
|
|
|
453 |
rank() over (order by disk_reads desc) ranking
|
|
|
454 |
from
|
|
|
455 |
(
|
|
|
456 |
select
|
|
|
457 |
address,
|
|
|
458 |
disk_reads,
|
|
|
459 |
executions,
|
|
|
460 |
100 * ratio_to_report(disk_reads) over () pct
|
|
|
461 |
from
|
|
|
462 |
sys.v_\$sql
|
|
|
463 |
where
|
|
|
464 |
command_type != 47 and module != 'T.O.A.D.'
|
|
|
465 |
)
|
|
|
466 |
where
|
|
|
467 |
disk_reads > 50 * executions
|
|
|
468 |
) s,
|
|
|
469 |
sys.v_\$sqltext p
|
|
|
470 |
where
|
|
|
471 |
s.ranking <= $numsql and
|
|
|
472 |
p.address = s.address
|
|
|
473 |
order by
|
|
|
474 |
1 desc, s.address, p.piece
|
|
|
475 |
";
|
|
|
476 |
global $ADODB_CACHE_MODE;
|
|
|
477 |
if (isset($_GET['expeixora']) && isset($_GET['sql'])) {
|
|
|
478 |
$partial = empty($_GET['part']);
|
|
|
479 |
echo "<a name=explain></a>".$this->Explain($_GET['sql'],$partial)."\n";
|
|
|
480 |
}
|
|
|
481 |
if (isset($_GET['sql'])) {
|
|
|
482 |
$var = $this->_ExpensiveSQL($numsql);
|
|
|
483 |
return $var;
|
|
|
484 |
}
|
|
|
485 |
|
|
|
486 |
$s = '';
|
|
|
487 |
$s .= $this->_ExpensiveSQL($numsql);
|
|
|
488 |
$s .= '<p>';
|
|
|
489 |
$save = $ADODB_CACHE_MODE;
|
|
|
490 |
$ADODB_CACHE_MODE = ADODB_FETCH_NUM;
|
|
|
491 |
if ($this->conn->fetchMode !== false) $savem = $this->conn->SetFetchMode(false);
|
|
|
492 |
|
|
|
493 |
$savelog = $this->conn->LogSQL(false);
|
|
|
494 |
$rs =& $this->conn->Execute($sql);
|
|
|
495 |
$this->conn->LogSQL($savelog);
|
|
|
496 |
|
|
|
497 |
if (isset($savem)) $this->conn->SetFetchMode($savem);
|
|
|
498 |
$ADODB_CACHE_MODE = $save;
|
|
|
499 |
|
|
|
500 |
if ($rs) {
|
|
|
501 |
$s .= "\n<h3>Ixora Expensive SQL</h3>";
|
|
|
502 |
$s .= $this->tohtml($rs,'expeixora');
|
|
|
503 |
}
|
|
|
504 |
|
|
|
505 |
return $s;
|
|
|
506 |
}
|
|
|
507 |
|
|
|
508 |
}
|
|
|
509 |
?>
|