Presentation is loading. Please wait.

Presentation is loading. Please wait.

The quest for Actual Rows

Similar presentations


Presentation on theme: "The quest for Actual Rows"— Presentation transcript:

1 The quest for Actual Rows
Explaining SQL Path The quest for Actual Rows

2 Explain Choices EXPLAIN (v7+) AUTOTRACE (v8i+) SQL_TRACE (v7+)
Estimated plan at time of EXPLAIN, w/rights of connection AUTOTRACE (v8i+) Had to be explicitly configured. Remember TRACEONLY or you get all data back. Could be actual plan. Buggy. Does not peek. Can pollute cursor cache with non-optimized plans (observation affects execution). SQL_TRACE (v7+) Hard to use. Grab trace and tkprof on DB host. Need host acct. Must enable trace before run; multiple routes to enable. DBMS_XPLAN (v9i+) Installed and available by default. Can explain SQL after run. Actual plan at the time it ran and w/rights of the SQL executor. Fairly easy to use. Multiple routes to use it.

3 Rowsource Statistics Vital to seeing actuals during performance tuning. Stored in V$SQL_PLAN_STATISTICS[_ALL] Based on SYS tables X$QESRSTAT and X$QESRSTATALL Added in 9i, but no great way to see them Query SYS V$ views Trace file, STAT# rows or as actuals in tkprof report DBMS_XPLAN.display_cursor (easier and more complete) Enabled by: Setting STATISTICS_LEVEL = ALL Adding GATHER_PLAN_STATISTICS hint to query Enabling SQL Trace

4 Rowsource Statistics Figures stored in V$SQL_PLAN_STATISTICS[_ALL] contain cumulative and last execution If interested in one particular execution, may best to use sql trace and tkprof (some articles say otherwise) If statistics_level can’t be set, or query can’t be hinted: Enable sql trace for the session (various methods) Enable sql trace for the sql_id (11g): SQL> alter system set events 'sql_trace[sql:b1ur7k0b50xxq]';

5 DBMS_XPLAN display (9i) estimated plan from plan table
display_cursor (10g) real plan from memory display_awr (10g) real, historical plan from AWR display_sqlset (10g) statements stored in a SQL tuning set display_sql_plan_baseline (11g) one or more execution plans for the specified SQL handle of a SQL plan baseline

6 display_cursor() Requires SELECT priv on V$SQL_PLAN_STATISTICS_ALL, V$SQL and V$SQL_PLAN Simplest form of explaining a plan is: SELECT * FROM TABLE(dbms_xplan.display_cursor()); Grabs last statement executed in the session. Use TOAD or SQL*Plus. Bug in PL/SQL Developer PSD: Join to V$SQL and search sql_text to get sql_id implicitly. May have to “tag” SQL to find it. If using SQL*Plus, format with: SET PAGESIZE 0 SET LINESIZE 180 COLUMN plan_table_output FORMAT a180 Not RAC aware – verify can only explain local sql_id. I doubt it.

7 display_cursor() Examples: My favorite: SELECT plan_table_output
dbms_xplan.display_cursor([sql_id], [child_number], [format]) Examples: SELECT * FROM TABLE(dbms_xplan.display_cursor); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor(format => 'TYPICAL -parallel')); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',null,'BASIC')); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,null)); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'TYPICAL')); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'SERIAL')); SELECT * FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'ALL')); -- isn't really all SELECT * FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'ADVANCED')); -- includes outline SELECT * FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'ALL outline')); -- equals advanced SELECT * FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'ALL peeked_binds')); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'ALL ALLSTATS')); SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor('at64wqf50y1sn',0,'ALL IOSTATS')); My favorite: SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor(format => 'ALLSTATS peeked_binds'));

8 sql_id Defaults to NULL
NULL will cause the plan of the last cursor executed by the session to be displayed Does not work in PL/SQL Developer. Does work in SQL*Plus. SQL_ID of the SQL statement in the cursor cache. Retrieve SQL_ID from V$SQL or V$SQLAREA. Alternatively, you could choose the column PREV_SQL_ID for a specific session out of V$SESSION.

9 sql_id Can be obtained indirectly by searching for something unique in the SQL statement of interest: SELECT plan_table_output FROM v$sql s ,TABLE(dbms_xplan.display_cursor(s.sql_id, s.child_number, 'basic')) t WHERE s.sql_text LIKE 'SELECT prod_category%';

10 sql_id DEFAULT is NULL. Supposed to get the last cursor used by the session. For some odd reason, this does not work in PL/SQL Developer SQL Window or Command Window. Only works in SQL*Plus.

11 child_number Child number of the cursor to display.
If not supplied, the execution plan of all cursors matching the supplied sql_id are displayed. The child_number can be specified only if sql_id is specified. In RAC, it is possible to see duplicate sql_id and child_number across instances in gv$sql. Connect to the right instance and query v$sql

12 GATHER_PLAN_STATISTICS
SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM emp e NATURAL JOIN dept d WHERE e.ename = 'SMITH'; SET LINESIZE 130 SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format => 'ALLSTATS LAST')); | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | | 0 | SELECT STATEMENT | | | | |00:00:00.01 | | | 1 | NESTED LOOPS | | | | |00:00:00.01 | | | 2 | NESTED LOOPS | | | | |00:00:00.01 | | |* 3 | TABLE ACCESS FULL | EMP | | | |00:00:00.01 | | |* 4 | INDEX UNIQUE SCAN | PK_DEPT | | | |00:00:00.01 | | | 5 | TABLE ACCESS BY INDEX ROWID| DEPT | | | |00:00:00.01 | |

13 format BASIC NULL TYPICAL (DEFAULT) SERIAL ALL ADVANCED
None of the good stuff NULL bytes, cost, note, predicate and rows TYPICAL (DEFAULT) NULL + parallel, partition, and remote SERIAL TYPICAL – parallel and remote ALL TYPICAL + alias, projection ADVANCED ALL + outline Mentioned in 10.1 docs, but not since. Still supported. Undocumented peeked_binds IOSTATS, MEMSTATS, ALLSTATS, LAST Exclude details by preceding options with “-”

14 Using display_cursor SET PAGESIZE 0 SET LINESIZE 180
COLUMN plan_table_output FORMAT a180 SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor(format => 'parallel peeked_binds')); -- If using GATHER_PLAN_STATISTICS to see actuals... SELECT plan_table_output FROM TABLE(dbms_xplan.display_cursor(format => 'ALLSTATS parallel peeked_binds'));

15 V$SQL A treasure trove of good information.
SELECT u.username, vs.inst_id ,vs.sql_id, vs.plan_hash_value, vs.child_number, vcs.peeked ,vs.executions, vs.buffer_gets ,vs.is_bind_sensitive AS bind_snstv, vs.is_bind_aware AS bind_aware, vs.is_shareable AS shareable ,vs.last_load_time, vs.last_active_time ,vs.sql_plan_baseline ,vs.sql_text ,ROUND(vs.cpu_time * (1 / ), 1) AS cpu_secs ,ROUND(vs.elapsed_time * (1 / ), 1) AS elapsed_secs ,vs.disk_reads ,vs.physical_read_requests phys_read_req ,ROUND(((vs.physical_read_bytes / 1024) / 1024), 1) AS phys_read_mbytes FROM gv$sql vs JOIN dba_users u ON u.user_id = vs.parsing_user_id LEFT JOIN gv$sql_cs_statistics vcs ON vcs.sql_id = vs.sql_id AND vcs.child_number = vs.child_number WHERE vs.sql_id IN (SELECT sql_id FROM gv$sql WHERE dbms_lob.instr(sql_fulltext, '&piece_of_sql') > 0 AND dbms_lob.instr(sql_fulltext, 'vs.sql_id') = 0) AND u.username = UPPER('&schema_name') ORDER BY vs.last_active_time DESC;

16 Data dictionary goodies
-- much like v$sql, but has extra sauce SELECT * FROM gv$sqlarea WHERE sql_id = '&sql_id'; -- showed that bind_mismatch is Y, and hash_match_failed is Y for 11g slow plan SELECT * FROM gv$sql_shared_cursor WHERE sql_id = '&sql_id'; -- value_string shows the bind variable captured (odd there are six rows for two executions) SELECT * FROM gv$sql_bind_capture WHERE sql_id = '&sql_id' AND child_number = &child_num; -- showed that slow 11g plan was peeked SELECT * FROM gv$sql_cs_statistics WHERE sql_id = '&sql_id'; -- histogram taken during peek SELECT * FROM gv$sql_cs_histogram WHERE sql_id = '&sql_id'; -- showed we didn't have baselines turned on and auto-gathering SELECT * FROM dba_sql_plan_baselines;

17 Bind Peeking Maria Colgan’s piece: Looking at binds peeked vs. passed:

18 Multiple Plans v$sql_shared_cursor Check cursor_sharing parameter

19 Reading Plans Execution plans can look very confusing, but reading them is reasonably simple provided you follow three simple rules: The first operation, or starting point, is the first leaf node, when reading from the top to the bottom. That is, the first element without an indented entry below it. You read from that point backwards. Join operations always require two sets. The order you read the sets is top down, so the first set is the driving set and the second is the probed set. In the case of a nested loop, the first set is the outer loop. In the case of a hash join, the first set is used to build the hash table. One join is performed at a time, so you only need to consider two sets and their join operation at any one time.

20 Reading Plans Looking at the following execution plan, the order of the operations is 4, 5, 3, 6, 2, 9, 10, 8, 7, 1, 0. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | | 0 | SELECT STATEMENT | | | | (15)| 00:00:01 | |* 1 | HASH JOIN | | | | (15)| 00:00:01 | | 2 | NESTED LOOPS | | | | | | | 3 | NESTED LOOPS | | | | (0)| 00:00:01 | |* 4 | TABLE ACCESS FULL | DEPARTMENTS | | | (0)| 00:00:01 | |* 5 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | | | (0)| 00:00:01 | | 6 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | | | (0)| 00:00:01 | | 7 | VIEW | index$_join$_004 | | | (34)| 00:00:01 | |* 8 | HASH JOIN | | | | | | | 9 | INDEX FAST FULL SCAN | EMP_NAME_IX | | | (0)| 00:00:01 | | 10 | INDEX FAST FULL SCAN | EMP_EMP_ID_PK | | | (0)| 00:00:01 |

21 11g Adaptive Cursor Sharing (ACS)
“In Oracle Database 11g, the optimizer has been enhanced to allow multiple execution plans to be used for a single statement that uses bind variables. This ensures that the best execution plan will be used depending on the bind value. A cursor will be marked bind sensitive if the optimizer believes the optimal plan may depend on the value of the bind variable…A cursor is typically marked bind sensitive, because there is a histogram on the column with the bind variable.” - Oracle

22 11g ACS If this is true, then too many statements will be marked as bind sensitive and too many statements monitored for changing bind values, if every column in our database has a histogram.

23 11g ACS “If a different bind value is used in a subsequent execution, it will use the same execution plan because Oracle initially assumes it can be shared. However, the execution statistics for this new bind value will be recorded and compared to the execution statistics for the previous value. If Oracle determines that the new bind value caused the data volumes manipulated by the query to be significantly different it "adapts" its behavior so that the same plan is not always shared for this query. Hence a new plan will be generated based on the new bind value and the cursor is marked bind-aware.” - Oracle

24 11g ACS “Note that the original cursor generated for the statement will be discarded when the cursor switches to bind aware mode. This is a one-time overhead. The cursor is marked as not-shareable (v$sql.is_shareable = N), which means the cursor will be among the first to be aged out of the cursor cache, and that it will no longer be used.” - Oracle

25 11g Adaptive Cursor Sharing
“ACS doesn’t seem to be completely cooked yet. In fact, it seems to be somewhat of a futile attempt, since in the very best case, one execution with a bad plan would be necessary for the optimizer to recognize that a bind variable peeking issue existed. This wouldn’t be so bad if the information was persisted, so that the same “learning” process wouldn’t have to be endured if/when a statement gets flushed from the shared pool. This issue alone is enough to keep this feature from being relied upon in situations where performance is critical. In my opinion, the best approach remains unchanged from version 10, that being the judicious use of literals where necessary to prevent plan instability due to bind variable peeking.” - Kerry Osborne


Download ppt "The quest for Actual Rows"

Similar presentations


Ads by Google