SQL Query Tuning Tips for OracleGet it Right the First TimeDean RichardsLead DBA, Confio Software2/21/2013 1
2/21/2013 Confidential - Internal Use Only 2Who Am I?• 20+ Years in Oracle & SQL Server– DBA and Developer– Worked for Ora...
2/21/2013 3Agenda• Introduction• Which Query Should I Tune?• Query Plans• SQL Diagramming– Who registered yesterday for Tu...
2/21/2013 Confidential - Internal Use Only 4Why Focus on Queries• Most Applications– Read and Write data to/from database–...
2/21/2013 Confidential - Internal Use Only 5Who Should Tune• Developers?– Developing applications is very difficult– Typic...
2/21/2013 Confidential - Internal Use Only 6Which SQL• User / Batch Job Complaints• Queries Performing Most I/O (LIO, PIO)...
2/21/2013 Confidential - Internal Use Only 7SQL Wait States Understand the total time a Query spends in Database Measure...
2/21/2013 Confidential - Internal Use Only 8Oracle Wait InterfaceV$SQLSQL_IDSQL_FULLTEXTV$SESSIONSIDUSERNAMESQL_IDPROGRAMM...
2/21/2013 Confidential - Internal Use Only 9Oracle Wait InterfaceSELECT s.sql_id, sql.sql_text, sql.plan_hash_value,DECODE...
2/21/2013 Confidential - Internal Use Only 10SQL Plan• EXPLAIN PLAN– Estimated execution plan– Can be wrong for many reaso...
2/21/2013 Confidential - Internal Use Only 11DBMS_XPLANselect * from table (dbms_xplan.display_cursor(‘&SQLID’,ChildNo));P...
2/21/2013 Confidential - Internal Use Only 12All Plans Not EqualSELECT company, attribute FROM data_out WHERE segment = :B...
2/21/2013 Confidential - Internal Use Only 13Bind Values• V$SQL_BIND_CAPTURE– STATISTICS_LEVEL = TYPICAL or ALL– Collected...
2/21/2013 Confidential - Internal Use Only 14Case Studies• SQL Diagramming• Case Study 1– Who registered for Tuning Class ...
2/21/2013 Confidential - Internal Use Only 15Case Study 1• Who registered yesterday for SQL TuningSELECT s.fname, s.lname,...
2/21/2013 Confidential - Internal Use Only 16Database Diagram
2/21/2013 Confidential - Internal Use Only 17Execution Plan---------------------------------------------------------------...
2/21/2013 Confidential - Internal Use Only 18SQL Diagrammingregistrationstudent class51301.03.001select count(1) from regi...
2/21/2013 Confidential - Internal Use Only 19New Execution Plan• Execution Stats – 11,168 Logical Reads• Why does a Full T...
2/21/2013 Confidential - Internal Use Only 20Database Diagram
2/21/2013 Confidential - Internal Use Only 21New Execution PlanCREATE INDEX reg_alt ON registration(class_id)• Execution S...
2/21/2013 Confidential - Internal Use Only 22Case Study 2• Lookup order status for callerSELECT o.OrderID, c.LastName, p.P...
2/21/2013 Confidential - Internal Use Only 23Case Study 2• Lookup order status for callerSELECT o.OrderID, c.LastName, p.P...
2/21/2013 Confidential - Internal Use Only 24Database Diagram
2/21/2013 Confidential - Internal Use Only 25-----------------------------------------------------------------------------...
2/21/2013 Confidential - Internal Use Only 26SELECT COUNT(1) FROM CustomerWHERE LastName LIKE SMI%1917 / 52189 = .04SELECT...
2/21/2013 Confidential - Internal Use Only 27• Only 0.5% of rows are <> ‘C’• How about changing the query?– AND o.OrderSta...
2/21/2013 Confidential - Internal Use Only 28New Execution PlanCREATE INDEX order_status ON Orders (OrderStatus)Execution ...
2/21/2013 Confidential - Internal Use Only 29• Tuning SQL gives more “bang for the buck”• Make sure you are tuning the cor...
Q&AThank you for attending.More questions?Contact Dean atDeanRichards@confio.comDownload free trial of Ignite athttp//www....
Upcoming SlideShare
Loading in …5
×

Oracle Query Tuning Tips - Get it Right the First Time

629 views
546 views

Published on

Whether you are a developer or DBA, this presentation will outline a method for determining the best approach for tuning a query every time by utilizing response time analysis and SQL Diagramming techniques. Regardless of the complexity of the statement or database platform being utilized (this method works on all), this quick and systematic approach will lead you down the correct
tuning path with no guessing. If you are a beginner or expert, this approach will save you countless hours tuning a query.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
629
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Oracle Query Tuning Tips - Get it Right the First Time

  1. 1. SQL Query Tuning Tips for OracleGet it Right the First TimeDean RichardsLead DBA, Confio Software2/21/2013 1
  2. 2. 2/21/2013 Confidential - Internal Use Only 2Who Am I?• 20+ Years in Oracle & SQL Server– DBA and Developer– Worked for Oracle SPG• Lead DBA for Confio Software– DeanRichards@confio.com– Makers of Ignite8 Response Time Analysis Tools– http://www.ignitefree.com – only free RTA Tool• Specialize in Performance Tuning
  3. 3. 2/21/2013 3Agenda• Introduction• Which Query Should I Tune?• Query Plans• SQL Diagramming– Who registered yesterday for Tuning Class– Check order status
  4. 4. 2/21/2013 Confidential - Internal Use Only 4Why Focus on Queries• Most Applications– Read and Write data to/from database– Simple manipulation of data– Deal with smaller amounts of data• Most Databases– Examine larger amounts of data, return a little– Inefficiencies quickly become bottleneck• Why do SQL tuning?– Tuning SQL - “Gives the most bang for your buck”– Changes to SQL are Safer– ~85% of performance issues are SQL related
  5. 5. 2/21/2013 Confidential - Internal Use Only 5Who Should Tune• Developers?– Developing applications is very difficult– Typically focused on functionality– Not much time left to tune SQL– Do not get enough practice– SQL runs differently in Production than Dev/Test• DBA?– Do not know the code like developers do– Focus on “Keep the Lights On”– Very complex environment• Need a team approach– But also need someone to lead the effort
  6. 6. 2/21/2013 Confidential - Internal Use Only 6Which SQL• User / Batch Job Complaints• Queries Performing Most I/O (LIO, PIO)• Queries Consuming CPU• Queries Doing Full Table Scans• Known Poorly Performing SQL• Tracing a Session / Process• Highest Response Times (Ignite for Oracle)select sql_text, elapsed_time, cpu_time, executions,sql_id, hash_value, last_active_time,plan_hash_value, program_id, module, actionfrom v$sqlorder by elapsed_time/
  7. 7. 2/21/2013 Confidential - Internal Use Only 7SQL Wait States Understand the total time a Query spends in Database Measure time while Query executes SQL Server helps by providing Wait TypesFocus on Response Time
  8. 8. 2/21/2013 Confidential - Internal Use Only 8Oracle Wait InterfaceV$SQLSQL_IDSQL_FULLTEXTV$SESSIONSIDUSERNAMESQL_IDPROGRAMMODULEACTIONPLAN_HASH_VALUEROW_WAIT_OBJ#V$SQLAREASQL_IDEXECUTIONSPARSE_CALLSBUFFER_GETSDISK_READSV$SESSION_WAITSIDEVENTP1, P1RAW, P2, P2RAW, P3, P3RAWSTATE (WAITING, WAITED…)• Oracle 10g added this info to V$SESSIONV$SQL_PLANSQL_IDPLAN_HASH_VALUEDBA_OBJECTSOBJECT_IDOBJECT_NAMEOBJECT_TYPE
  9. 9. 2/21/2013 Confidential - Internal Use Only 9Oracle Wait InterfaceSELECT s.sql_id, sql.sql_text, sql.plan_hash_value,DECODE(s.state, WAITING, s.event, CPU/LogicalIO) waitevent,s.p1, s.p2, s.p3FROM v$session s, v$sql sqlWHERE s.sql_id = sql.sql_idAND s.sql_address = sql.addressAND program = ‘…’ AND s.sid = …AND <whatever else you know>
  10. 10. 2/21/2013 Confidential - Internal Use Only 10SQL Plan• EXPLAIN PLAN– Estimated execution plan– Can be wrong for many reasons– What most tools show you• V$SQL_PLAN (Oracle 9i+)– Real execution plan– Use DBMS_XPLAN for display• Confio Ignite for Oracle– Gathers real plan– Shows it historically
  11. 11. 2/21/2013 Confidential - Internal Use Only 11DBMS_XPLANselect * from table (dbms_xplan.display_cursor(‘&SQLID’,ChildNo));PLAN_TABLE_OUTPUT--------------------------------------------------------------------------------SQL_ID f7jqysdfu2f2s, child number 0-------------------------------------update emp set hire_date = to_date(:1) where id=:2Plan hash value: 1494045816---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | UPDATE STATEMENT | | | | 3025 (100)| || 1 | UPDATE | EMP | | | | ||* 2 | TABLE ACCESS FULL| EMP | 122 | 2684 | 3025 (1)| 00:00:37 |---------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------2 - filter("ID"=3247)
  12. 12. 2/21/2013 Confidential - Internal Use Only 12All Plans Not EqualSELECT company, attribute FROM data_out WHERE segment = :B1• Wait Time – 100% on “db file scattered read”• Plan from EXPLAIN PLAN• Plan from V$SQL_PLAN using DBMS_XPLAN
  13. 13. 2/21/2013 Confidential - Internal Use Only 13Bind Values• V$SQL_BIND_CAPTURE– STATISTICS_LEVEL = TYPICAL or ALL– Collected at 15 minute intervalsSELECT name, position, datatype_string, value_stringFROM v$sql_bind_captureWHERE sql_id = 15uughacxfh13;NAME POSITION DATATYPE_STRING VALUE_STRING----- ---------- --------------- ------------:B1 1 BINARY_DOUBLE 189• Bind Values also provided by tracing– Level 4 – bind values– Level 8 – wait information– Level 12 – bind values and wait information
  14. 14. 2/21/2013 Confidential - Internal Use Only 14Case Studies• SQL Diagramming• Case Study 1– Who registered for Tuning Class yesterday• Case Study 2– Check order status
  15. 15. 2/21/2013 Confidential - Internal Use Only 15Case Study 1• Who registered yesterday for SQL TuningSELECT s.fname, s.lname, r.signup_dateFROM student sINNER JOIN registration r ON s.student_id = r.student_idINNER JOIN class c ON r.class_id = c.class_idWHERE c.name = SQL TUNINGAND r.signup_date BETWEEN :1 AND :2AND r.cancelled = N• Execution Stats – 12,634 Logical Reads
  16. 16. 2/21/2013 Confidential - Internal Use Only 16Database Diagram
  17. 17. 2/21/2013 Confidential - Internal Use Only 17Execution Plan----------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |----------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 7 | 819 | 3173 (5)| 00:00:39 ||* 1 | FILTER | | | | | || 2 | NESTED LOOPS | | | | | || 3 | NESTED LOOPS | | 7 | 819 | 3173 (5)| 00:00:39 ||* 4 | HASH JOIN | | 7 | 448 | 3166 (5)| 00:00:38 ||* 5 | TABLE ACCESS FULL | CLASS | 1 | 45 | 22 (0)| 00:00:01 ||* 6 | TABLE ACCESS FULL | REGISTRATION | 8334 | 154K| 3144 (5)| 00:00:38 ||* 7 | INDEX UNIQUE SCAN | PK_STUDENT | 1 | | 0 (0)| 00:00:01 || 8 | TABLE ACCESS BY INDEX ROWID| STUDENT | 1 | 53 | 1 (0)| 00:00:01 |----------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------1 - filter(TRUNC(SYSDATE@!-1)<=TRUNC(SYSDATE@!))4 - access("R"."CLASS_ID"="C"."CLASS_ID")5 - filter("C"."NAME"=SQL TUNING)6 - filter("R"."SIGNUP_DATE">=TRUNC(SYSDATE@!-1) AND "R"."CANCELLED"=N AND"R"."SIGNUP_DATE"<=TRUNC(SYSDATE@!))7 - access("S"."STUDENT_ID"="R"."STUDENT_ID")
  18. 18. 2/21/2013 Confidential - Internal Use Only 18SQL Diagrammingregistrationstudent class51301.03.001select count(1) from registration where cancelled = Nand signup_date between 2012-12-05 00:00 and 2012-12-06 00:0054,554 / 1,639,186 = 0.03select count(1) from class where name = SQL TUNING2 / 1,267 = .001• Great Book - “SQL Tuning” by Dan Tow– Teaches SQL Diagramming– http://www.singingsql.com
  19. 19. 2/21/2013 Confidential - Internal Use Only 19New Execution Plan• Execution Stats – 11,168 Logical Reads• Why does a Full Table Scan still occur on REGISTRATION?------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 7 | 819 | 3153 (5)| 00:00:38 ||* 1 | FILTER | | | | | || 2 | NESTED LOOPS | | | | | || 3 | NESTED LOOPS | | 7 | 819 | 3153 (5)| 00:00:38 ||* 4 | HASH JOIN | | 7 | 448 | 3146 (5)| 00:00:38 || 5 | TABLE ACCESS BY INDEX ROWID| CLASS | 1 | 45 | 2 (0)| 00:00:01 ||* 6 | INDEX RANGE SCAN | CL_NAME | 1 | | 1 (0)| 00:00:01 ||* 7 | TABLE ACCESS FULL | REGISTRATION | 8334 | 154K| 3144 (5)| 00:00:38 ||* 8 | INDEX UNIQUE SCAN | PK_STUDENT | 1 | | 0 (0)| 00:00:01 || 9 | TABLE ACCESS BY INDEX ROWID | STUDENT | 1 | 53 | 1 (0)| 00:00:01 |------------------------------------------------------------------------------------------------CREATE INDEX cl_name ON class(name)
  20. 20. 2/21/2013 Confidential - Internal Use Only 20Database Diagram
  21. 21. 2/21/2013 Confidential - Internal Use Only 21New Execution PlanCREATE INDEX reg_alt ON registration(class_id)• Execution Stats – 4,831 Logical Reads------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 7 | 819 | 2415 (1)| 00:00:29 ||* 1 | FILTER | | | | | || 2 | NESTED LOOPS | | | | | || 3 | NESTED LOOPS | | 7 | 819 | 2415 (1)| 00:00:29 || 4 | NESTED LOOPS | | 7 | 448 | 2408 (1)| 00:00:29 || 5 | TABLE ACCESS BY INDEX ROWID| CLASS | 1 | 45 | 2 (0)| 00:00:01 ||* 6 | INDEX RANGE SCAN | CL_NAME | 1 | | 1 (0)| 00:00:01 ||* 7 | TABLE ACCESS BY INDEX ROWID| REGISTRATION | 7 | 133 | 2406 (1)| 00:00:29 ||* 8 | INDEX RANGE SCAN | REG_ALT | 2667 | | 9 (0)| 00:00:01 ||* 9 | INDEX UNIQUE SCAN | PK_STUDENT | 1 | | 0 (0)| 00:00:01 || 10 | TABLE ACCESS BY INDEX ROWID | STUDENT | 1 | 53 | 1 (0)| 00:00:01 |------------------------------------------------------------------------------------------------
  22. 22. 2/21/2013 Confidential - Internal Use Only 22Case Study 2• Lookup order status for callerSELECT o.OrderID, c.LastName, p.ProductID, p.Description,sd.ActualShipDate, sd.ShipStatus, sd.ExpectedShipDateFROM Orders oINNER JOIN Item i ON i.OrderID = o.OrderIDINNER JOIN Customer c ON c.CustomerID = o.CustomerIDINNER JOIN ShipmentDetails sd ON sd.ShipmentID = i.ShipmentIDINNER JOIN Product p ON p.ProductID = i.ProductIDINNER JOIN Address a ON a.AddressID = sd.AddressIDWHERE c.LastName LIKE NVL(:1,) || %AND c.FirstName LIKE NVL(:2,) || %AND o.OrderDate >= SYSDATE - 30AND o.OrderStatus <> C• Execution Stats – 73,600 Logical Reads
  23. 23. 2/21/2013 Confidential - Internal Use Only 23Case Study 2• Lookup order status for callerSELECT o.OrderID, c.LastName, p.ProductID, p.Description,sd.ActualShipDate, sd.ShipStatus, sd.ExpectedShipDateFROM Orders oINNER JOIN Item i ON i.OrderID = o.OrderIDINNER JOIN Customer c ON c.CustomerID = o.CustomerIDINNER JOIN ShipmentDetails sd ON sd.ShipmentID = i.ShipmentIDINNER JOIN Product p ON p.ProductID = i.ProductIDINNER JOIN Address a ON a.AddressID = sd.AddressIDWHERE c.LastName LIKE SMI%AND c.FirstName LIKE %AND o.OrderDate >= SYSDATE - 30AND o.OrderStatus <> C• Execution Stats – 73,600 Logical Reads
  24. 24. 2/21/2013 Confidential - Internal Use Only 24Database Diagram
  25. 25. 2/21/2013 Confidential - Internal Use Only 25--------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 6 | 1164 | 4892 (2)| 00:00:59 || 1 | NESTED LOOPS | | | | | || 2 | NESTED LOOPS | | 6 | 1164 | 4892 (2)| 00:00:59 || 3 | NESTED LOOPS | | 6 | 510 | 4886 (2)| 00:00:59 ||* 4 | HASH JOIN | | 105 | 5460 | 4782 (2)| 00:00:58 ||* 5 | HASH JOIN | | 1320 | 44880 | 4118 (2)| 00:00:50 ||* 6 | TABLE ACCESS FULL | SHIPMENTDETAILS | 304 | 6080 | 1070 (2)| 00:00:13 || 7 | TABLE ACCESS FULL | ITEM | 3588K| 47M| 3036 (1)| 00:00:37 ||* 8 | TABLE ACCESS FULL | ORDERS | 54903 | 965K| 663 (3)| 00:00:08 ||* 9 | TABLE ACCESS BY INDEX ROWID| CUSTOMER | 1 | 33 | 1 (0)| 00:00:01 ||* 10 | INDEX UNIQUE SCAN | PK_CUSTOMER | 1 | | 0 (0)| 00:00:01 ||* 11 | INDEX UNIQUE SCAN | PK_PRODUCT | 1 | | 0 (0)| 00:00:01 || 12 | TABLE ACCESS BY INDEX ROWID | PRODUCT | 1 | 109 | 1 (0)| 00:00:01 |--------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------4 - access("I"."ORDERID"="O"."ORDERID")5 - access("SD"."SHIPMENTID"="I"."SHIPMENTID")6 - filter("SD"."SHIPSTATUS"<>C)8 - filter("O"."ORDERDATE">=SYSDATE@!-30)9 - filter("C"."LASTNAME" LIKE SMI%)10 - access("C"."CUSTOMERID"="O"."CUSTOMERID")11 - access("P"."PRODUCTID"="I"."PRODUCTID")Execution Plan
  26. 26. 2/21/2013 Confidential - Internal Use Only 26SELECT COUNT(1) FROM CustomerWHERE LastName LIKE SMI%1917 / 52189 = .04SELECT COUNT(1) FROM OrdersWHERE OrderDate >= SYSDATE - 3055067 / 690671 = .08SELECT COUNT(1) FROM OrdersWHERE OrderStatus <> C3760 / 690671 = .005o .08.04i cpsda.005SQL Diagram
  27. 27. 2/21/2013 Confidential - Internal Use Only 27• Only 0.5% of rows are <> ‘C’• How about changing the query?– AND o.OrderStatus = I• Add an Index on OrderStatus– Collect histogramsSELECT OrderStatus, COUNT(1)FROM OrdersGROUP BY OrderStatusI 3760C 686911Data Skew Problems
  28. 28. 2/21/2013 Confidential - Internal Use Only 28New Execution PlanCREATE INDEX order_status ON Orders (OrderStatus)Execution Stats – 7,221 Logical Reads-----------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1581 | 301K| 3722 (1)| 00:00:45 ||* 1 | HASH JOIN | | 1581 | 301K| 3722 (1)| 00:00:45 ||* 2 | HASH JOIN | | 1581 | 270K| 2655 (1)| 00:00:32 || 3 | NESTED LOOPS | | | | | || 4 | NESTED LOOPS | | 1581 | 101K| 2587 (1)| 00:00:32 ||* 5 | HASH JOIN | | 303 | 15756 | 170 (1)| 00:00:03 ||* 6 | TABLE ACCESS BY INDEX ROWID| ORDERS | 303 | 5757 | 33 (0)| 00:00:01 ||* 7 | INDEX RANGE SCAN | ORDER_STATUS | 3811 | | 9 (0)| 00:00:01 ||* 8 | VIEW | index$_join$_001 | 2055 | 67815 | 137 (1)| 00:00:02 ||* 9 | HASH JOIN | | | | | ||* 10 | INDEX RANGE SCAN | CUSTOMER_LN | 2055 | 67815 | 14 (8)| 00:00:01 || 11 | INDEX FAST FULL SCAN | PK_CUSTOMER | 2055 | 67815 | 123 (0)| 00:00:02 ||* 12 | INDEX RANGE SCAN | PK_ORDERINFO | 5 | | 2 (0)| 00:00:01 || 13 | TABLE ACCESS BY INDEX ROWID | ITEM | 5 | 70 | 8 (0)| 00:00:01 || 14 | TABLE ACCESS FULL | PRODUCT | 8914 | 948K| 68 (0)| 00:00:01 || 15 | TABLE ACCESS FULL | SHIPMENTDETAILS | 836K| 15M| 1064 (1)| 00:00:13 |-----------------------------------------------------------------------------------------------------
  29. 29. 2/21/2013 Confidential - Internal Use Only 29• Tuning SQL gives more “bang for the buck”• Make sure you are tuning the correct query• Use Wait Events and Response Time Analysis– Locking problems may not be a Query Tuning issue– Wait events tell you where to start• Use “Real Execution Plans”– Get plan_hash_value from V$SESSION, V$SQL– Pass it to V$SQL_PLAN to get Real Plan• Ignite – Does All of Above For You– OEM Does not Give you Enough Details• SQL Diagramming - “Get it right the First Time”Takeaway Points
  30. 30. Q&AThank you for attending.More questions?Contact Dean atDeanRichards@confio.comDownload free trial of Ignite athttp//www.confio.com2/21/2013 30

×