Watching SQL Execute on Oracle - Part II - Page 2July 9, 2004 V$SQL_OPTIMIZER_ENVDuring the course and life of a database, applications and sessions typically will begin to alter their environments to optain the best performance. It can sometimes be very hard to track down anyone with this information, let alone extract the information from either in-house or third party code. For this reason you can use the V$SQL_OPTIMIZER_ENV view to pull from memory the actual optimizer environment the individual SQL is executing. Table 3 shows the subset of columns that are used from this view in order to see the values for the optimizer's environment. Listing 3 shows the SQL to do this join for active SQL and a subset of the output it generates. Table 3
Listing 3
select sesion.sid,
sesion.username,
name,
isdefault,
value
from v$sql_optimizer_env sql_optimizer_env, v$session sesion
where sesion.sql_hash_value = sql_optimizer_env.hash_value
and sesion.sql_address = sql_optimizer_env.address
and sesion.username is not null
Optimizer environment settings for current active SQL
SID USERNAME NAME ISD VALUE
---- ------------ ---------------------------------------- --- ----------
149 JKOOPMANN parallel_execution_enabled YES true
149 JKOOPMANN optimizer_features_enable YES 10.1.0
149 JKOOPMANN cpu_count YES 2
149 JKOOPMANN active_instance_count YES 1
149 JKOOPMANN parallel_threads_per_cpu YES 2
149 JKOOPMANN hash_area_size YES 131072
149 JKOOPMANN bitmap_merge_area_size YES 1048576
149 JKOOPMANN sort_area_size YES 65536
149 JKOOPMANN sort_area_retained_size YES 0
Extract the Execution PlanIf you are tired of extracting the raw SQL_TEXT and formatting it and then running it through the old method of producing explain plans, this section is for you. There is an Oracle object called DBMS_XPLAN that allows you to supply the SQL_ID and SQL_CHILD_NUMBER and have it produce a nicely formatted explain output. Listing 4 gives an example SQL query that uses the SQL_ID and SQL_CHILD_NUMBER we obtained earlier from V$SESSION and gives the output of the query. Listing 4
SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR(('5qk509xugpmpv'),1));
Explain output
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID 5qk509xugpmpv, child number 1
-------------------------------------
SELECT count(*) FROM sys.dba_tables WHERE owner = :1
Plan hash value: 580517646
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|Time|
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 242 (100)| |
| 1 | SORT AGGREGATE | | 1 | 149 | | |
| 2 | NESTED LOOPS | | 1 | 149 | 242 (1)| 03 |
| 3 | MERGE JOIN CARTESIAN | | 1 | 136 | 218 (1)| 03 |
| 4 | NESTED LOOPS OUTER | | 1 | 81 | 194 (1)| 03 |
| 5 | NESTED LOOPS OUTER | | 1 | 78 | 193 (1)| 03 |
| 6 | NESTED LOOPS OUTER | | 1 | 70 | 192 (1)| 03 |
| 7 | NESTED LOOPS OUTER | | 1 | 59 | 191 (1)| 03 |
| 8 | NESTED LOOPS | | 1 | 54 | 191 (1)| 03 |
|* 9 | HASH JOIN | | 8 | 368 | 183 (1)| 03 |
| 10 | NESTED LOOPS | | 7 | 119 | 4 (0)| 01 |
| 11 | TABLE ACCESS BY INDEX ROWID| USER$ | 1 | 14 | 1 (0)| 01 |
|* 12 | INDEX UNIQUE SCAN | I_USER1 | 1 | | 0 (0)| |
| 13 | TABLE ACCESS FULL | TS$ | 7 | 21 | 3 (0)| 01 |
|* 14 | TABLE ACCESS FULL | TAB$ | 16 | 464 | 178 (0)| 03 |
|* 15 | TABLE ACCESS BY INDEX ROWID | OBJ$ | 1 | 8 | 1 (0)| 01 |
|* 16 | INDEX UNIQUE SCAN | I_OBJ1 | 1 | | 0 (0)| |
|* 17 | INDEX UNIQUE SCAN | I_OBJ1 | 1 | 5 | 0 (0)| |
| 18 | TABLE ACCESS CLUSTER | SEG$ | 1 | 11 | 1 (0)| 01 |
|* 19 | INDEX UNIQUE SCAN | I_FILE#_BLOCK# | 1 | | 0 (0)| |
| 20 | TABLE ACCESS BY INDEX ROWID | OBJ$ | 1 | 8 | 1 (0)| 01 |
|* 21 | INDEX UNIQUE SCAN | I_OBJ1 | 1 | | 0 (0)| |
| 22 | TABLE ACCESS CLUSTER | USER$ | 1 | 3 | 1 (0)| 01 |
|* 23 | INDEX UNIQUE SCAN | I_USER# | 1 | | 0 (0)| |
| 24 | BUFFER SORT | | 1 | 55 | 217 (1)| 03 |
|* 25 | FIXED TABLE FULL | X$KSPPI | 1 | 55 | 24 (0)| 01 |
|* 26 | FIXED TABLE FIXED INDEX | X$KSPPCV (ind:2) | 1 | 13 | 24 (0)| 01 |
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
9 - access("T"."TS#"="TS"."TS#")
12 - access("U"."NAME"=:1)
14 - filter(BITAND("T"."PROPERTY",1)=0)
15 - filter("O"."OWNER#"="U"."USER#")
16 - access("O"."OBJ#"="T"."OBJ#")
17 - access("T"."BOBJ#"="CO"."OBJ#")
19 - access("T"."TS#"="S"."TS#" AND "T"."FILE#"="S"."FILE#" AND "T"."BLOCK#"="S"."BLOCK#")
21 - access("T"."DATAOBJ#"="CX"."OBJ#")
23 - access("CX"."OWNER#"="CU"."USER#")
25 - filter("KSPPI"."KSPPINM"='_dml_monitoring_enabled')
26 - filter("KSPPI"."INDX"="KSPPCV"."INDX")
|
|
Column |
Description |
|
|
This is the address to the parent of this cursor/sql |
|
|
This is the hash value to the parent statement in the library cache |
|
|
Plan hash value |
|
|
The number for each step in the execution plan |
|
|
The number of rows returned |
|
|
Number of consistent gets for the last run of the plan for a given step. |
|
|
Number of physical disk reads for the last run of the plan for a given step |
Listing 5
Extracting the statistics for a single execution of a SQL
statement
select sesion.sid,
sesion.username,
sql_plan_statistics.operation_id "Id",
sql_plan_statistics.last_output_rows "Rows",
sql_plan_statistics.last_cr_buffer_gets "Consistent Gets",
sql_plan_statistics.last_disk_reads "Disk Reads"
from v$sql_plan_statistics sql_plan_statistics, v$session sesion
where sesion.sql_hash_value = sql_plan_statistics.hash_value
and sesion.sql_address = sql_plan_statistics.address
and sesion.username is not null
Explain output
SID USERNAME Id Rows Consistent Gets Disk Reads
--- -------------- ---------- ---------- --------------- ----------
149 JKOOPMANN 1 1 8594 0
149 JKOOPMANN 2 643 8594 0
149 JKOOPMANN 3 643 8594 0
149 JKOOPMANN 4 643 8594 0
149 JKOOPMANN 5 643 7540 0
149 JKOOPMANN 6 643 6369 0
149 JKOOPMANN 7 643 4614 0
149 JKOOPMANN 8 643 3969 0
149 JKOOPMANN 9 1572 823 0
149 JKOOPMANN 10 7 11 0
149 JKOOPMANN 11 1 2 0
149 JKOOPMANN 12 1 1 0
149 JKOOPMANN 13 7 9 0
149 JKOOPMANN 14 1572 812 0
149 JKOOPMANN 15 643 3146 0
149 JKOOPMANN 16 1572 1574 0
149 JKOOPMANN 17 50 645 0
149 JKOOPMANN 18 555 1755 0
149 JKOOPMANN 19 555 645 0
149 JKOOPMANN 20 526 1171 0
149 JKOOPMANN 21 526 645 0
149 JKOOPMANN 22 526 1054 0
149 JKOOPMANN 23 526 2 0
149 JKOOPMANN 24 643 0 0
149 JKOOPMANN 25 1 0 0
149 JKOOPMANN 26 643 0 0
Determining what SQL is executing within the Oracle engine and watching its access path and the true statistical values accumulated for each run are invaluable. Give these scripts a try, add to them, and you too can begin to finally determine what SQL is executing within your environment.