View
7
Download
0
Category
Preview:
Citation preview
Gary GordhamerManaging Principal Consultant
Viscosity North America
29 years of IT experience 28 years with Oracle (6.x up to 19c)
Worked in many different industries including healthcare, manufacturing, utilities, banking, and marketing
@ggordhamlinkedin.com/in/ggordhamer/oraontap.blogspot.com
Note: The views in this presentation are my own and do represent the views of the company I work for.
@ViscosityNAviscosityna.com
Want to try this out / follow along?
You can download all the scripts from GitHubhttps://github.com/ggordham/ora-presentations/tree/main/indepth-sql-RMOUGOr: https://bit.ly/3uWmoOa bit.ly / 3uWmoOa
All information are ”as is” and meant for teaching purposes only.DO NOT run these in any production system or system relied upon by your development teams.
@ViscosityNAviscosityna.com
So, you have a bad SQL statement?
Options to change the performance of a bad SQL:– Look at environment setup (like statistics / missing index)– Change the SQL / add a HINT– Apply a SQL PROFILE– Use a SQL PLAN BASELINE– Create and apply a SQL PATCH
Step 1 in this process is to identify how a SQL statement is performingStep 2 what is a better performance option for that SQL statementStep 3 apply a fix from the list above
@ViscosityNAviscosityna.com
Agenda
• SQL Tuning Intro• SQL T• Cost Based Optimizer Tracing• Digging into the Optimizer• Reading Trace Files• Tricks to Force the Optimizer
@ViscosityNAviscosityna.com
SQL Tuning
SQL Statement – what data you want Oracle to retrieveExecution Plan – method Oracle will use to retrieve the data
SELECT sum(t1.c), sum(t2.c)FROM t1, t2WHERE t1.a = t2.aAND t1.d = :1
Oracle Optimizer
Object Metadata Object Statistics
System Statistics
SQL BaselinePlan1 --2 –-3 –-4 --
SQL Profile(execution Statistics) Plan
1 --2 –-3 –-4 --
Plan List
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
ExecuteOptimizer
Environment
SQL Tuning – the art of affecting one or more parts of this process to decrees execution time or resource consumption
1. Submit SQL 2. Collect Information 3. Generate Possible Plans 4. Check Baselines 5. Pick PlanExecute!
@ViscosityNAviscosityna.com
SQL Tuning – Deep Dive
Why a deep dive?• Oracle automation tools are not helping• Critical / Complex SQL that used to work, what changed?• System upgrade, why is the optimizer acting differently?
We are covering tools that you will need to know how to use• When to use them is up to you• Tuning is more of an art
@ViscosityNAviscosityna.com
SQL Tuning – Basic Steps
1. Document the issue (capture information)a) SQL Statement IDb) Current Execution planc) Current performance / Resource usage
2. Identify the goal (target performance)3. Try the standard tools
a) Explain plan – look for bad decisions (ignoring indexes, etc)b) Statistics – look for missing or stale statisticsc) SQL Profile – provide the optimizer more informationd) SQL Baseline – force a specific plan that is already available
4. Deep DiveNote: take lots of notes, the deeper you go the more lost you will get!
@ViscosityNAviscosityna.com
SQL Tuning – Deep Dive – Be Prepared
Have your scripts readyCapture / save off information logsBe prepared to compare / review a lot of dataBe prepared to repeat steps / retry again, and again
Don’t be surprised if things change”Sifting Sand” – frequently the system changes while you are watching it
@ViscosityNAviscosityna.com
Optimizer SQL Steps
SQL Syntax Check OptimizationSemantic
Check
Shared Pool
Check
ParsingRow Source Generation Execution
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
GenerateMultiple
Execution Plan Options Query Plan
(make Outline)
Shared Pool
Soft Parse
Hard Parse ->
Plan1 --2 –-3 –-4 --
Object
StatisticsSystem Statistics
SQL
Profile
Baseline/*+ --
–-–-
*/
Outline/*+ --
–-–-
*/
Note: Soft Parsing is impacted by bind variable values
@ViscosityNAviscosityna.com
SQL Tuning – These Tools Show Me What?
Explain Plan – What steps will be taken to execute the SQL
SQL Health Check – What is the status / details of all the objects touched by the SQL
SQL Trace – What happened when the SQL was executed
CBO Trace – How did the Optimizer decide to execute the SQL
SQLT – Everything + some “Observations”
@ViscosityNAviscosityna.com
SQL Tuning – Deep Dive – Tools
Runs Statement
SQL Execution
StepsObject
InformationDatabase
EnvironmentHTML
ReportsEasy to
readRequires
Install Explain Plan Maybe Yes No No Maybe Yes NoSQL Monitor Maybe Yes No No Yes Yes NoSQL Health Check (HC) No Yes Extensivie Yes Yes Yes NoSQL Trace Yes Yes Little Maybe No No NoCBO Trace Yes Yes Extensivie Some No No NoSQLT Maybe Yes Extensivie Extensivie Yes Yes Yes
Number of tools to choose from, using the right tool for the situation
@ViscosityNAviscosityna.com
SQLT or SQLTXPlain
Set of scripts from Oracle – SQLT is diagnostics or debugging information– SQLT needs to be installed in the database– To use SQLT, the parsing schema needs to be granted SQLT_USER_ROLE
Captures:– Database environment and configuration– All statistics related to the SQL run– Object detailed information (definitions, statistics, etc..)– SQL text, explain plan– Observations– Store's data so it can be transferred to another DB for testing / comparison
@ViscosityNAviscosityna.com
Installing SQLT
You will need:• SQLT scripts (download from MOS note 1614107.1)• Tablespace to store SQLT information• Name of a TEMP tablespace to use• Password to assign to the SQLTPLAIN schema
SQLT install will create / change:• Schema SQLTXPLAIN to store objects / run traces• Schema SQLTXADMIN • Role SQLT_USER_ROLE to grant to parsing schemas
@ViscosityNAviscosityna.com
SQLT Provides 7 Methods for diagnostics
Standard runs– XECUTE – run the SQL and collect the details– XPLAIN – uses EXPLAIN plan, is blind to bind peaking
Pulling data from AWR– XTRACT – pulls data from AWR for given SQL_ID– XTRXEC – pulls data from AWR and executes SQL to get most complete data
For DG or Standby Read Only databases:– XTRSBY – see MOS Doc ID 2450388.1 for more details on grants and setup– XPLAIN – uses EXPLAIN plan, is blind to bind peaking
For faster SQLT runs on repeated tries– XPREXT – disables some features of XTRACT for faster SQLT runs– XPREXC – disables some features of XECUTE for faster SQLT runs
@ViscosityNAviscosityna.com
SQLT Basic Steps to Run
Scripts are in the sqlt/run directorySQL> start sqltxplain.sql my_sql.txt my_sqltxplain_password
Note: sql_fua0hb5hfst77.txt is a file with a single SQL statement in it.This example uses “Explain Plan” and does not actually run the SQL statement and provides less details.
For extensive details, use XTRACT method that executes the statement:SQL> start sqltxtract.sql sql_id my_sqltxplain_password
SQL> start sqltxplain.sql sql_fua0hb5hfst77.txt Oracle_4U
SQL> start sqltxtract.sql fua0hb5hfst77 Oracle_4U
@ViscosityNAviscosityna.com
SQLT - Files / Reportssqlt_s39942_log.zip – database alert logsqlt_s39943_purge.sql – SQL script to purge this statement from SQLT tablessqlt_20210309_1117_fua0hb5hfst77_H.zip – This is your trace
Length Date Time Name--------- ---------- ----- ----
256869 03-09-2021 11:12 sqlt_s39943_10053_explain.trc - Explain Plan trace843 03-09-2021 11:16 sqlt_s39943_addmrpt_0002.zip - ADDM Report
147460 03-09-2021 11:15 sqlt_s39943_awrrpt_0002.zip - AWR Report710 03-09-2021 11:16 sqlt_s39943_cell_state.zip - Exadata Storage Cell status7769 03-09-2021 11:16 sqlt_s39943_driver.zip - Scripts used during SQLT25623 03-09-2021 11:12 sqlt_s39943_lite.html - Simple report (Like SQLHC)
2220853 03-09-2021 11:16 sqlt_s39943_log.zip - Logs from steps of SQLT1443813 03-09-2021 11:12 sqlt_s39943_main.html - Main SQLT Report149613 03-09-2021 11:16 sqlt_s39943_opatch.zip - OPatch logs captured14729 03-09-2021 11:12 sqlt_s39943_readme.html - Additional Instructions1872 03-09-2021 11:12 sqlt_s39943_sql_detail_active.html – SQL Monitor Report391 03-09-2021 11:16 sqlt_s39943_tc_script.sql - Script to re-run same SQL124 03-09-2021 11:16 sqlt_s39943_tc_sql.sql - Just the SQL traced
79072 03-09-2021 11:16 sqlt_s39943_tcx.zip - SQLT full data exported436250 03-09-2021 11:16 sqlt_s39943_tc.zip - SQLT test case scripts104192 03-09-2021 11:16 sqlt_s39943_trc.zip - SQL Trace files113927 03-09-2021 11:17 sqlt_s39943_sqldx.zip - CSV of SQLT information
@ViscosityNAviscosityna.com
Looking at SQLT
Look at the execution plans (is there more than one)Look at the Plan Performance StatisticsLook at Plan Performance History (did something change?)From the execution plan, look for poor performing steps
Table ScansNested Loops (sometimes)Hash Joins (sometimes)
Look into the objects (indexes that were not picked up)Look at statistics / histograms on columns in predicate part of the query
This is an art; you might be looking for needles in a haystack!
@ViscosityNAviscosityna.com
Why SQLT vs Explain Plan?
Provides all the details when the query was traced– DB environment– SQL history
Provides bind variable details, and bind peaking informationEach part of the report links to the data you need– On plan, need to see statistics for that object, click ->
Multiple plans if they existExtreme details on ”other” information– Baselines / Profiles / Patches etc..
Provides some nice SQL / other useful items
@ViscosityNAviscosityna.com
Why SQL Trace
Collects information on a SQL runningData is collected in a trace file (external to DB)Trace file needs to be processed with TKPROF toolNo additional items to installRequires some access to the database server to get trace file
Requires “ALTER SESSION” privilege
DBA can trace an active or in process session
@ViscosityNAviscosityna.com
What’s in a SQL Trace?
What happened during the execution of the statementProcess with TKPROF tool (normally in DB home directory)
Helpful to see where time was spentCan give a “limited” explain plan (requires DB login)
I would always get a full explain plan for the statement as well(DBMS_XPLAN functions based on where you are capturing it from)
@ViscosityNAviscosityna.com
Running a Trace
Set the trace file name (easier to find in DIAGNOSTIC_DEST)ALTER SESSION SET tracefile_identifier = 'mytrace01';
Turn tracing onEXEC DBMS_SESSION.SET_SQL_TRACE(sql_trace => true);
Execute one or more SQL statementsSQL>Be sure to turn tracing off!EXEC DBMS_SESSION.SET_SQL_TRACE(sql_trace => false);
Find the trace file in the database trace directory (DIAGNOSTIC_DEST)<SID>_ora_<PID>_<ID>.trc
@ViscosityNAviscosityna.com
Run trace through TKPROF
On the DB server run TKPROF$ tkprof t1db_ora_32683_tdemo2.trc t1db_ora_32683_tdemo2.out explain=perflab
TKPROF: Release 19.0.0.0.0 - Development on Fri Mar 19 16:18:24 2021
Copyright (c) 1982, 2019, Oracle and/or its affiliates. All rights reserved.
password =
You will be prompted for the user password provided after explain=Look at the .out file
$ Less t1db_ora_32683_tdemo2.out
@ViscosityNAviscosityna.com
TKPROF Output – Sample Execution 1
Details of what happened during SQL Execution (from trace)call count cpu elapsed disk query current rows------- ------ -------- ---------- ---------- ---------- ---------- ----------Parse 1 0.00 0.00 0 0 0 0Execute 1 0.00 0.00 0 0 0 0Fetch 2 0.01 0.01 0 1981 0 1------- ------ -------- ---------- ---------- ---------- ---------- ----------total 4 0.01 0.02 0 1981 0 1
Misses in library cache during parse: 0Optimizer mode: ALL_ROWSParsing user id: 136 (PERFLAB)Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT AGGREGATE (cr=1981 pr=0 pw=0 time=12670 us starts=1)1 1 1 NESTED LOOPS (cr=1981 pr=0 pw=0 time=12642 us starts=1 cost=553 size=22 card=1)1 1 1 NESTED LOOPS (cr=1980 pr=0 pw=0 time=12586 us starts=1 cost=553 size=22 card=1)1 1 1 TABLE ACCESS FULL T1 (cr=1977 pr=0 pw=0 time=12523 us starts=1 cost=550 size=13 card=1)1 1 1 INDEX RANGE SCAN T2I (cr=3 pr=0 pw=0 time=58 us starts=1 cost=2 size=0 card=1)(object
id 139465)1 1 1 TABLE ACCESS BY INDEX ROWID T2 (cr=1 pr=0 pw=0 time=46 us starts=1 cost=3 size=9 card=1)
@ViscosityNAviscosityna.com
TKPROF Output – Sample Execution 2
Explain plan vs:Plan hash value: 3534348942--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 741K(100)| || 1 | SORT AGGREGATE | | 1 | 22 | | || 2 | NESTED LOOPS | | 246K| 5305K| 741K (1)| 00:00:29 || 3 | NESTED LOOPS | | 246K| 5305K| 741K (1)| 00:00:29 ||* 4 | TABLE ACCESS FULL | T1 | 246K| 3134K| 550 (1)| 00:00:01 ||* 5 | INDEX RANGE SCAN | T2I | 1 | | 2 (0)| 00:00:01 || 6 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 9 | 3 (0)| 00:00:01 |--------------------------------------------------------------------------------------
Rows (1st) Rows (avg) Rows (max) Row Source Operation---------- ---------- ---------- ---------------------------------------------------
1 1 1 SORT AGGREGATE (cr=11089 pr=0 pw=0 time=426057 us starts=1)250001 250001 250001 NESTED LOOPS (cr=11089 pr=0 pw=0 time=444330 us starts=1 cost=741506 size=5432438 card=246929)250001 250001 250001 NESTED LOOPS (cr=9118 pr=0 pw=0 time=290903 us starts=1 cost=741506 size=5432438 card=246929)250001 250001 250001 TABLE ACCESS FULL T1 (cr=1976 pr=0 pw=0 time=36524 us starts=1 cost=550 size=3210077 card=246929)250001 250001 250001 INDEX RANGE SCAN T2I (cr=7142 pr=0 pw=0 time=185318 us starts=250001 cost=2 size=0 card=1)(object id 139465)250001 250001 250001 TABLE ACCESS BY INDEX ROWID T2 (cr=1971 pr=0 pw=0 time=93985 us starts=250001 cost=3 size=9 card=1)
Trace
@ViscosityNAviscosityna.com
SQL Trace – 10046 – MOS Note 376442.1
ALTER SESSION SET EVENTS '10046 trace name context forever, level 12’;
• 0 The debugging event is disabled.• 1 The debugging event is enabled. For each processed database call, the following information is given:
SQL statement, response time, service time, number of processed rows, number of logical reads, number of physical reads and writes, execution plan, and little additional information. an execution plan is written to the trace file only after the first execution of every cursor. The execution statistics associated to it are the ones of the first execution only.
• 4 additional information about bind variables. Mainly, the data type, its precision, and the value used for each execution.• 8 level 1, plus detailed information about wait time. For each wait experienced during the processing, the following information
is given: the name of the wait event, the duration, and a few additional parameters identifying the resource that has been waited for.
• 16 level 1, plus the execution plans information is written to the trace file for each execution. • 32 level 1, but without the execution plans information.• 64 level 1, plus the execution plans information might be written for executions following the first one.
The condition is that, since the last write of execution plans information, a particular cursor consumed at least one additionalminute of DB time. This level is interesting in two cases. First, when the information about the first execution is not enough for analyzing a specific issue. Second, when the overhead of writing the information about every execution (level 16) is too high.
Level 12 (4 + 8): simultaneously enable level 4 and level 8.Level 28 (4 + 8 + 16): simultaneously enable level 4, level 8 and level 16.
@ViscosityNAviscosityna.com
Why SQL Cost Based Optimizer (CBO) Trace
Collects information on all steps the Optimizer takes– How the explain plans are generated– How the cost of the plan is generated–What object and system information was used
No additional items to installRequires some access to the database server to get trace file
Requires “ALTER SESSION” privilege
You need to flush the statement from cursor cache before trace!
@ViscosityNAviscosityna.com
Running a CBO Trace
Set the trace file name (easier to find in DIAGNOSTIC_DEST)ALTER SESSION SET tracefile_identifier = 'mycbotrace01';
Turn tracing onALTER SESSION SET timed_statistics = TRUE;ALTER SESSION SET statistics_level = all;ALTER SESSION SET max_dump_file_size = unlimited;-- CBO tracingALTER SESSION SET EVENTS '10053 trace name context forever, level 1'; -- Additional SQL trace informationALTER SESSION SET EVENTS '10046 trace name context forever, level 12';
Execute one or more SQL statementsSQL>
@ViscosityNAviscosityna.com
Running a CBO Trace – Cont.
Be sure to turn tracing off!ALTER SESSION SET EVENTS '10053 trace name context off'; ALTER SESSION SET EVENTS '10046 trace name context off';
Find the trace file in the database trace directory (DIAGNOSTIC_DEST)<SID>_ora_<PID>_<ID>.trc
This file can be very large! (10MB, 26MB etc.)
Another way to find the trace file:SQL> SELECT value
FROM v$diag_infoWHERE name = 'Default Trace File';
@ViscosityNAviscosityna.com
Running a CBO Trace – second method
CBO trace based on SQL ID (based on SQL ID in cursor cache)SQL> execute DBMS_SQLDIAG.DUMP_TRACE(-
p_sql_id=>'cjk13xfm8ybh7', -p_child_number=>0, -p_component=>'Optimizer', -p_file_id=>’mycbotrace02');
Find the trace file in the database trace directory (DIAGNOSTIC_DEST)<SID>_ora_<PID>_<ID>.trc
@ViscosityNAviscosityna.com
What Does the Optimizer do?
Like Google Maps, the optimizer is building a path Set of instructions to retrieve the data requested (or act on the data)• Object definition• Data statistical information• Access path options (Indexes, Partitions, Storage Cells, Cache)• Constraints (Joins and Filter options)
Let's walk through an example:• How would you sort out a bag of skittles?
@ViscosityNAviscosityna.com
How Would You?
How many candies of each color in a bag?How many candies of color blue in 5 bags?How many candies of color red in a large container?How many candies of color purple or yellow in 500 bags?
What if one person does this work?What if 10 people?Do you need one bowl?What if you have four bowls?
What would help you be more efficient?
@ViscosityNAviscosityna.com
What if You Had More Information
There are five colors (Yellow, Purple, Orange, Red, Green)Bag sizes:• Fun Size – 24 count• Original Size – 56 count• Party size – 50oz • Jar – 54ozWhat if you had five people to help?What if the colors were pre-sorted?
@ViscosityNAviscosityna.com
Normal distribution?
Normal distribution – five colors • Fun Size – 24 count = 24/5 = 4.8 of each color• Original Size – 2.17oz – 56 count = 11.2 of each color• Family size – 27.5oz = estimate 141.2 of each color• Jar – 54oz = estimate 278.7 of each color
Two original size bags – will you get 12 green each? Or 11? Or maybe 10?What if the distribution is not “normal”?
You need 24 green skittles
@ViscosityNAviscosityna.com
Some Terminology
• NDV - number of distinct values = unique possibilities– Age – 0 to probably 110?– Skittles colors – five (yellow, green, red, orange, purple)– U.S. Zip Codes – 41,688
• Cardinality – the percent of records that match a value or set of values– Estimate - ”normal distribution”– Actual – based on analysis of data
• #Rows – total number of rows in the table• AvgRowLen – number of bytes per row (inside a block)• Selectivity – how many rows will be retrieved (estimate)
@ViscosityNA
Example Tables
Tables t1 and t2Each has 500,000 rows of the same data
OWNER SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME NO_EXTENTS SEG_SIZE-------- ------------- ------------ --------------- ---------- -----------PERFLAB T1 TABLE USERS 31 16,777,216
ROWNUM OWNER SEGMENT_NAME BYTES BLOCKS------ -------- ------------- ---------- ----------
1 PERFLAB T1 65536 816 PERFLAB T1 65536 817 PERFLAB T1 1048576 12831 PERFLAB T1 1048576 128
@ViscosityNA
First Example – No Stats
Table has 500K rows, why 160K estimate?– Segment size 16MB (from pervious slide) / 100 row length
Table: T2 Alias: T2 (NOT ANALYZED)#Rows: 164259 SSZ: 0 LGR: 0 #Blks: 2011 AvgRowLen: 100.00
---------------------------------------+-----------------------------------+| Id | Operation | Name | Rows | Bytes | Cost | Time |---------------------------------------+-----------------------------------+| 0 | SELECT STATEMENT | | | | 1096 | || 1 | SORT AGGREGATE | | 1 | 65 | | || 2 | HASH JOIN | | 1643 | 104K | 1096 | 00:00:14 || 3 | TABLE ACCESS FULL | T1 | 1643 | 63K | 548 | 00:00:07 || 4 | TABLE ACCESS FULL | T2 | 160K | 4171K | 547 | 00:00:07 |---------------------------------------+-----------------------------------+
SELECT sum(t1.c), sum(t2.c) FROM t1, t2 WHERE t1.a = t2.a AND t1.d = :idnum
@ViscosityNA
Second Example –Stats
Table: T2 Alias: T2: #Rows: 500000 SSZ: 0 LGR: 0 #Blks: 2011 AvgRowLen: 23.00 Column (#4): D(NUMBER)
AvgLen: 4 NDV: 253072 Nulls: 0 Density: 0.000004 Min: 1.000000 Max: 250000.000000Estimated selectivity: 0.0000039514 , col: #4
Card: Original: 500000.000000 Rounded: 2 Computed: 1.975722 Non Adjusted: 1.975722
-------------------------------------------------+-----------------------------------+| Id | Operation | Name | Rows | Bytes | Cost | Time |-------------------------------------------------+-----------------------------------+| 0 | SELECT STATEMENT | | | | 556 | || 1 | SORT AGGREGATE | | 1 | 22 | | || 2 | NESTED LOOPS | | 2 | 44 | 556 | 00:00:07 || 3 | NESTED LOOPS | | 2 | 44 | 556 | 00:00:07 || 4 | TABLE ACCESS FULL | T1 | 2 | 26 | 550 | 00:00:07 || 5 | INDEX RANGE SCAN | T2I | 1 | | 2 | 00:00:01 || 6 | TABLE ACCESS BY INDEX ROWID | T2 | 1 | 9 | 3 | 00:00:01 |-------------------------------------------------+-----------------------------------+
SELECT sum(t1.c), sum(t2.c) FROM t1, t2 WHERE t1.a = t2.a AND t1.d = :idnum
Estimates2 rowsor < 1%
@ViscosityNA
Second Example –Stats + Histograms
Column (#4): D(NUMBER)AvgLen: 4 NDV: 253072 Nulls: 0 Density: 0.000002 Min: 1.000000 Max: 250000.000000Histogram: Hybrid #Bkts: 254 UncompBkts: 5433 EndPtVals: 254 ActualVal: yes
Estimated selectivity: 0.493858 , endpoint value predicate, col: #4 Card: Original: 500000.000000 Computed: 246929.000000 Non Adjusted: 246929.000000
---------------------------------------+-----------------------------------+| Id | Operation | Name | Rows | Bytes | Cost | Time |---------------------------------------+-----------------------------------+| 0 | SELECT STATEMENT | | | | 1893 | || 1 | SORT AGGREGATE | | 1 | 22 | | || 2 | HASH JOIN | | 241K | 5305K | 1893 | 00:00:23 || 3 | TABLE ACCESS FULL | T1 | 241K | 3135K | 550 | 00:00:07 || 4 | TABLE ACCESS FULL | T2 | 488K | 4395K | 549 | 00:00:07 |---------------------------------------+-----------------------------------+
SELECT sum(t1.c), sum(t2.c) FROM t1, t2 WHERE t1.a = t2.a AND t1.d = :idnum
We went from:2 rows24,6929 rowsOr 49.3%
@ViscosityNA
What have I not been telling you?
Tables t1 and t2• Each has 50,000 rows• Column D – 250,001 rows value = 10– 249,999 rows “random” unique value
So, if I search for d=10–Oracle must find ½ the table
If I search for d=1000–Oracle must find 1 record
Joining 2 tables using “most” of the data – Hash Join
Joining 2 tables looking for just 1 record in each table –Nested Loops
@ViscosityNAviscosityna.com
Execution Plans Are Not Absolutes!
An execution plan can have different costsA SQL may run better with different execution plans at different timesPlan stability tools can help and can hurt performance– SQL Profiles are statistical information on generating plans– SQL Baselines allow for multiple plans– SQL Patches are the “hammer” of the toolset
Your system will change over time– Data growth / change– Hardware changes– Software changes
Your tuning methodology needs to adapt to change!
@ViscosityNAviscosityna.com
Optimizer Estimate vs Reality
------------------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows | A-Time | Buffers | Reads |------------------------------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | | | 553 (100)| 1 |00:00:00.04 | 1978 | 1976 || 1 | SORT AGGREGATE | | 1 | 1 | 22 | | 1 |00:00:00.04 | 1978 | 1976 || 2 | NESTED LOOPS | | 1 | 1 | 22 | 553 (1)| 1 |00:00:00.04 | 1978 | 1976 || 3 | NESTED LOOPS | | 1 | 1 | 22 | 553 (1)| 1 |00:00:00.04 | 1977 | 1975 ||* 4 | TABLE ACCESS FULL | T1 | 1 | 1 | 13 | 550 (1)| 1 |00:00:00.04 | 1974 | 1972 ||* 5 | INDEX RANGE SCAN | T2I | 1 | 1 | | 2 (0)| 1 |00:00:00.01 | 3 | 3 || 6 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 1 | 9 | 3 (0)| 1 |00:00:00.01 | 1 | 1 |------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows | A-Time | Buffers | Reads |------------------------------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | | | 553 (100)| 1 |00:00:01.00 | 11089 | 4536 || 1 | SORT AGGREGATE | | 1 | 1 | 22 | | 1 |00:00:01.00 | 11089 | 4536 || 2 | NESTED LOOPS | | 1 | 1 | 22 | 553 (1)| 250K|00:00:00.93 | 11089 | 4536 || 3 | NESTED LOOPS | | 1 | 1 | 22 | 553 (1)| 250K|00:00:00.36 | 9118 | 2566 ||* 4 | TABLE ACCESS FULL | T1 | 1 | 1 | 13 | 550 (1)| 250K|00:00:00.05 | 1976 | 1971 ||* 5 | INDEX RANGE SCAN | T2I | 250K| 1 | | 2 (0)| 250K|00:00:00.34 | 7142 | 595 || 6 | TABLE ACCESS BY INDEX ROWID| T2 | 250K| 1 | 9 | 3 (0)| 250K|00:00:00.45 | 1971 | 1970 |------------------------------------------------------------------------------------------------------------------------------
@ViscosityNAviscosityna.com
Same Query, Different Bind Value
---------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows | A-Time | Buffers |---------------------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | | | 553 (100)| 1 |00:00:00.01 | 1980 || 1 | SORT AGGREGATE | | 1 | 1 | 22 | | 1 |00:00:00.01 | 1980 || 2 | NESTED LOOPS | | 1 | 1 | 22 | 553 (1)| 1 |00:00:00.01 | 1980 || 3 | NESTED LOOPS | | 1 | 1 | 22 | 553 (1)| 1 |00:00:00.01 | 1979 ||* 4 | TABLE ACCESS FULL | T1 | 1 | 1 | 13 | 550 (1)| 1 |00:00:00.01 | 1976 ||* 5 | INDEX RANGE SCAN | T2I | 1 | 1 | | 2 (0)| 1 |00:00:00.01 | 3 || 6 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 1 | 9 | 3 (0)| 1 |00:00:00.01 | 1 |---------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| A-Rows | A-Time | Buffers |---------------------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | | | 741K(100)| 1 |00:00:00.43 | 11089 || 1 | SORT AGGREGATE | | 1 | 1 | 22 | | 1 |00:00:00.43 | 11089 || 2 | NESTED LOOPS | | 1 | 246K| 5305K| 741K (1)| 250K|00:00:00.44 | 11089 || 3 | NESTED LOOPS | | 1 | 246K| 5305K| 741K (1)| 250K|00:00:00.30 | 9118 ||* 4 | TABLE ACCESS FULL | T1 | 1 | 246K| 3134K| 550 (1)| 250K|00:00:00.04 | 1976 ||* 5 | INDEX RANGE SCAN | T2I | 250K| 1 | | 2 (0)| 250K|00:00:00.18 | 7142 || 6 | TABLE ACCESS BY INDEX ROWID| T2 | 250K| 1 | 9 | 3 (0)| 250K|00:00:00.09 | 1971 |---------------------------------------------------------------------------------------------------------------------
@ViscosityNAviscosityna.com
SQL Trace detail – Bind Variable Info / System stats
----- Bind Info (kkscoacd) -----Bind#0oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00oacflg=03 fl2=1000000 frm=00 csi=00 siz=24 off=0kxsbbbfp=7f6ddb4247f0 bln=22 avl=02 flg=05value=10
SYSTEM STATISTICS INFORMATION-----------------------------Using dictionary system stats.Using NOWORKLOAD StatsCPUSPEEDNW: 2761 millions instructions/sec (default is 100)IOTFRSPEED: 4096 bytes per millisecond (default is 4096)IOSEEKTIM: 10 milliseconds (default is 10)MBRC: NO VALUE blocks (default is 8)
@ViscosityNA
System Statistics
Stored in sys.aux_stats$ table, if you collect No Workload system stats:• CPUSPEEDNW Represents no-workload, average number of CPU cycles (millions/sec)• IOSEEKTIM Represents the time it takes to position the disk head to read data (ms)• IOTFRSPEED single random IO read request (bytes/ms)
If you have collected Workload system stats:• SREADTIM Single-block read time is the average time to read a single block randomly (ms)• MREADTIM Multiblock read is the average time to read a multiblock sequentially (ms)• CPUSPEED Represents workload average number of CPU cycles (millions/sec)• MBRC Average sequential multiblock read count (blocks)• MAXTHR Maximum throughput that the I/O subsystem can deliver (bytes/sec).• SLAVETHR Average parallel execution server I/O throughput (bytes/sec)
@ViscosityNA
System Statistics CommandsCreate a table to store the status– dbms_stats.create_stat_table(ownname => 'PERFLAB', stattab => 'SYS_STATS_LAB');
Run the stats gather (no workload or with workload)– dbms_stats.gather_system_stats(gathering_mode=>'NOWORKLOAD', statown=>'perflab', stattab=>'SYS_STATS_LAB', statid=>'PERFLAB_STATS_NW’);
– dbms_stats.gather_system_stats(gathering_mode=>'INTERVAL', interval=>10, statown=>'PERFLAB', stattab=>'SYS_STATS_LAB', statid=>'PERFLAB_STATS’);
– exec dbms_stats.gather_system_stats(gathering_mode=>'STOP', statown=>'PERFLAB', stattab=>'SYS_STATS_LAB', statid=>'PERFLAB_STATS');
Import the system stats– exec DBMS_STATS.IMPORT_SYSTEM_STATS (statown=>'PERFLAB', stattab=>'SYS_STATS_LAB', statid=>'PERFLAB_STATS’);
Delete System Stats– exec DBMS_STATS.delete_system_stats():
@ViscosityNAviscosityna.com
SQL Trace detail – Stats
Table Stats::Table: T1 Alias: T1#Rows: 500000 SSZ: 0 LGR: 0 #Blks: 2011 AvgRowLen: 23.00 NEB: 0 ChainCnt: 0.00 ScanRate: 0.00 SPC: 0
RFL: 0 RNF: 0 CBK: 0 CHR: 0 KQDFLG: 1#IMCUs: 0 IMCRowCnt: 0 IMCJournalRowCnt: 0 #IMCBlocks: 0 IMCQuotient: 0.000000Column (#3): C(NUMBER)AvgLen: 3 NDV: 1 Nulls: 0 Density: 0.000001 Min: 1.000000 Max: 1.000000Histogram: Freq #Bkts: 1 UncompBkts: 5223 EndPtVals: 1 ActualVal: yes
Column (#1): A(NUMBER)AvgLen: 6 NDV: 500000 Nulls: 0 Density: 0.000002 Min: 1.000000 Max: 1250000.000000Histogram: Hybrid #Bkts: 254 UncompBkts: 5225 EndPtVals: 254 ActualVal: yes
Index Stats::Index: T1I Col#: 1LVLS: 2 #LB: 1148 #DK: 500000 LB/K: 1.00 DB/K: 1.00 CLUF: 3942.00 NRW: 500000.00 SSZ: 0.00 LGR: 0.00 CBK: 0.00
GQL: 0.00 CHR: 0.00 KQDFLG: 8192 BSZ: 1
@ViscosityNAviscosityna.com
SQL Trace detail – Table Scan E.G. 1Access path analysis for EMPLOYEES***************************************SINGLE TABLE ACCESS PATH Single Table Cardinality Estimation for EMPLOYEES[E] SPD: Return code in qosdDSDirSetup: NOCTX, estType = TABLE
kkecdn: Single Table Predicate:"E"."STAFFNO"<=10Column (#5): STAFFNO(NUMBER)AvgLen: 4 NDV: 500 Nulls: 0 Density: 0.002000 Min: 1.000000 Max: 500.000000
Estimated selectivity: 0.020036 , col: #5Table: EMPLOYEES Alias: ECard: Original: 500.000000 Rounded: 10 Computed: 10.018036 Non Adjusted: 10.018036
Scan IO Cost (Disk) = 3.000000Scan CPU Cost (Disk) = 150607.200000Cost of predicates:io = NOCOST, cpu = 50.000000, sel = 0.020036 flag = 2048 ("E"."STAFFNO"<=10)
Total Scan IO Cost = 3.000000 (scan (Disk))+ 0.000000 (io filter eval) (= 0.000000 (per row) * 500.000000 (#rows))
= 3.000000Total Scan CPU Cost = 150607.200000 (scan (Disk))
+ 25000.000000 (cpu filter eval) (= 50.000000 (per row) * 500.000000 (#rows))= 175607.200000
Access Path: TableScanCost: 3.005902 Resp: 3.005902 Degree: 0Cost_io: 3.000000 Cost_cpu: 175607Resp_io: 3.000000 Resp_cpu: 175607
Best:: AccessPath: TableScanCost: 3.005902 Degree: 1 Resp: 3.005902 Card: 10.018036 Bytes: 0.000000
@ViscosityNAviscosityna.com
SQL Trace detail – Table Scan E.G. 2Access path analysis for T1***************************************SINGLE TABLE ACCESS PATH Single Table Cardinality Estimation for T1[T1] SPD: Return code in qosdDSDirSetup: NOCTX, estType = TABLEkkecdn: Single Table Predicate:"T1"."D"=:B1Column (#4): NewDensity:0.000002, OldDensity:0.000003 BktCnt:5225.000000, PopBktCnt:2633.000000, PopValCnt:1, NDV:253072
Column (#4): D(NUMBER)AvgLen: 4 NDV: 253072 Nulls: 0 Density: 0.000002 Min: 1.000000 Max: 250000.000000Histogram: Hybrid #Bkts: 254 UncompBkts: 5225 EndPtVals: 254 ActualVal: yes
Estimated selectivity: 0.493858 , endpoint value predicate, col: #4Table: T1 Alias: T1Card: Original: 500000.000000 Rounded: 246929 Computed: 246929.000000 Non Adjusted: 246929.000000
Scan IO Cost (Disk) = 546.000000Scan CPU Cost (Disk) = 119321215.840000Cost of predicates:io = NOCOST, cpu = 50.000000, sel = 0.493858 flag = 2048 ("T1"."D"=:B1)
Total Scan IO Cost = 546.000000 (scan (Disk))+ 0.000000 (io filter eval) (= 0.000000 (per row) * 500000.000000 (#rows))
= 546.000000Total Scan CPU Cost = 119321215.840000 (scan (Disk))
+ 25000000.000000 (cpu filter eval) (= 50.000000 (per row) * 500000.000000 (#rows))= 144321215.840000
Best:: AccessPath: TableScanCost: 550.355946 Degree: 1 Resp: 550.355946 Card: 246929.000000 Bytes: 0.000000
@ViscosityNAviscosityna.com
SQL Trace detail – Table JoinsJoin order[1]: T1[T1]#0 T2[T2]#1
Now joining: T2[T2]#1***************NL Join (NL - nested loops (join))Best NL cost: 741505.823354
resc: 741505.823354 resc_io: 741333.000000 resc_cpu: 5725983349 (Resc - resource cost)
Join Card: 246929.000000 = outer (246929.000000) * inner (500000.000000) * sel (2.0000e-06)Join Card - Rounded: 246929 Computed: 246929.000000
SM Join (SM - sort merge (join))SM cost: 4181.015172
resc: 4181.015172 resc_io: 4151.000000 resc_cpu: 994462669 (Resc - resource cost)SM Join (with index on outer)
HA Join (HA - hash (join))HA cost: 1893.061885
resc: 1893.061885 resc_io: 1881.000000 resc_cpu: 399634373 (Resc - resource cost)
Best:: JoinMethod: HashCost: 1893.061885 Degree: 1 Resp: 1893.061885 Card: 246929.000000 Bytes:
***********************Best so far: Table#: 0 cost: 550.355946 card: 246929.000000 bytes: 3210077.000000
Table#: 1 cost: 1893.061885 card: 246929.000000 bytes: 5432438.000000
*********************************Number of join permutations tried: 2
@ViscosityNAviscosityna.com
Playing With the Optimizer - 1
My SQL is not picking up an index.
1. Flush statement from cursor cache2. At session level set:
3. Run Explain Plan
Forcing indexes to be 99% less expensive than would normally be
ALTER SESSION SET optimizer_index_cost_adj = 1;
@ViscosityNAviscosityna.com
Playing With the Optimizer - 2
My SQL is not picking up an index.
1. Flush statement from cursor cache2. At session level set:
possible options are CHOOSE, CPU, IO3. Run Explain Plan
Forcing Optimizer to cost on a different resource
ALTER SESSION SET "_optimizer_cost_model"=IO;
@ViscosityNAviscosityna.com
Playing With the Optimizer - 3
My SQL is not picking up an index.
1. Flush statement from cursor cache2. At session level set:
3. Run Explain Plan
Are adaptive statistics helpful?Possibly run a trace in this process instead of just explain plan?
ALTER SESSION SET optimizer_adaptive_statistics=TRUE;
@ViscosityNAviscosityna.com
Optimizer SQL Steps
SQL Syntax Check OptimizationSemantic
Check
Shared Pool
Check
ParsingRow Source Generation Execution
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
Plan1 --2 –-3 –-4 --
GenerateMultiple
Execution Plan Options Query Plan
(make Outline)
Shared Pool
Soft Parse
Hard Parse ->
Plan1 --2 –-3 –-4 --
Object
StatisticsSystem Statistics
SQL
Profile
Baseline/*+ --
–-–-
*/
Outline/*+ --
–-–-
*/
*Explain will show soft parse detail if available
Note: Soft Parsing is impacted by bind variable values
Explain Plan* / MonitorSQL Health Check
SQL Trace SQLTXplain
CBO Trace
@ViscosityNAviscosityna.com
Wrapping Up
Have these tools ready to use!Know when each tool might be usefulOracle will tune a lot of things for you, but sometimes it wont
Don’t trace everything! Be surgical or specific!
Practice in non-production!
@ViscosityNAviscosityna.com
References
• Diagnostics for Query Tuning Problems (Doc ID 68735.1)• SQL Tuning Health-Check Script (SQLHC) (Doc ID 1366133.1)• SQLT Usage Instructions (Doc ID 1614107.1)• How To Collect 10046 Trace (SQL_TRACE) Diagnostics for Performance Issues (Doc ID 376442.1)• EVENT: 10046 "enable SQL statement tracing (including binds/waits)" (Doc ID 21154.1)• Interpreting Raw SQL_TRACE output (Doc ID 39817.1)• How to Obtain Tracing of Optimizer Computations (EVENT 10053) (Doc ID 225598.1)
Contact Viscosity @ViscosityNAviscosityna.com
Facebook.com/ViscosityNA
Linkedin.com/company/Viscosity-North-America
@ViscosityNA
Viscosity North America
@Viscosity_NA
Follow Us Online!
Recommended