Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

SQL Tuning and VST

2,145 views

Published on

Methodology to find a candidate for the optimal execution plan of a SQL query

Published in: Technology, Business
  • Be the first to comment

SQL Tuning and VST

  1. 1. Visual SQL Tuning (VST)Kyle Haileyhttp://dboptimizer.com
  2. 2. SQL TuningMethodology1. Find: Problem SQL2. Study: SQL Execution Plan3. Fix: How ?
  3. 3. Step 1 : Find “bad” SQL1. Users complain2. High Resources3. Monitoring
  4. 4. Step 2: Get Explain Plan--------------------------------------------------------------------------------------------| Id | Operation | Name | Starts | E-Rows | A-Rows |---------------------------------------------------------------------------------------------| 1 | HASH GROUP BY | | 1 | 1 | 1 ||* 2 | FILTER | | 1 | | 1909 ||* 3 | TABLE ACCESS BY INDEX ROWID | PS_RETROPAYPGM_TBL | 1 | 1 | 3413 || 4 | NESTED LOOPS | | 1 | 165 | 6827 ||* 5 | HASH JOIN | | 1 | 165 | 3413 ||* 6 | HASH JOIN | | 1 | 165 | 3624 || 7 | TABLE ACCESS BY INDEX ROWID | WB_JOB | 1 | 242 | 2895 || 8 | NESTED LOOPS | | 1 | 233 | 2897 || 9 | TABLE ACCESS BY INDEX ROWID| PS_PAY_CALENDAR | 1 | 1 | 1 ||* 10 | INDEX RANGE SCAN | PS0PAY_CALENDAR | 1 | 1 | 1 ||* 11 | INDEX RANGE SCAN | WBBJOB_B | 1 | 286 | 2895 ||* 12 | TABLE ACCESS FULL | WB_RETROPAY_EARNS | 1 | 27456 | 122K|| 13 | TABLE ACCESS FULL | PS_RETROPAY_RQST | 1 | 13679 | 13679 ||* 14 | INDEX RANGE SCAN | PS#RETROPAYPGM_TBL | 3413 | 1 | 3413 || 15 | SORT AGGREGATE | | 1791 | 1 | 1791 || 16 | FIRST ROW | | 1791 | 1 | 1579 ||* 17 | INDEX RANGE SCAN (MIN/MAX) | WB_JOB_F | 1791 | 1 | 1579 || 18 | SORT AGGREGATE | | 1539 | 1 | 1539 || 19 | FIRST ROW | | 1539 | 1 | 1539 ||* 20 | INDEX RANGE SCAN (MIN/MAX) | WB_JOB_G | 1539 | 1 | 1539 |---------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------2 - filter(("B"."EFFDT"= AND "B"."EFFSEQ"=))3 - filter("E"."OFF_CYCLE"="A"."PAY_OFF_CYCLE_CAL")5 - access("D"."RETROPAY_SEQ_NO"="C"."RETROPAY_SEQ_NO")6 - access("C"."EMPLID"="B"."EMPLID" AND "C"."EMPL_RCD#"="B"."EMPL_RCD#")10 - access("A"."RUN_ID"=PD2 AND "A"."PAY_CONFIRM_RUN"=N)11 - access("B"."COMPANY"="A"."COMPANY" AND "B"."PAYGROUP"="A"."PAYGROUP")12 - filter(("C"."RETROPAY_PRCS_FLAG"=C AND "C"."RETROPAY_LOAD_SW"=Y))14 - access("E"."RETROPAY_PGM_ID"="D"."RETROPAY_PGM_ID")17 - access("F"."EMPLID"=:B1 AND "F"."EMPL_RCD#"=:B2 AND "F"."EFFDT"<=:B3)20 - access("G"."EMPLID"=:B1 AND "G"."EMPL_RCD#"=:B2 AND "G"."EFFDT"=:B3)PARSING IN CURSOR #2 len=53 dep=0 uid=61 oct=3lid=61 tim=1151519905950403 hv=2296704914ad=4e50010cSELECT Hello, world; today is || SYSDATE FROM dualEND OF STMTPARSE#2:c=4000,e=1540,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,tim=1151519905950397BINDS #2:EXEC#2:c=0,e=58,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=1151519906034782WAIT #2: nam=SQL*Net message to client ela= 2 driverid=1650815232 #bytes=1 p3=0 obj#=-1tim=1151519906034809FETCH#2:c=0,e=29,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=1151519906034864WAIT #2: nam=SQL*Net message from client ela= 215driver id=1650815232 #bytes=1 p3=0 obj#=-1tim=1151519906035133FETCH#2:c=0,e=1,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=1151519906035165WAIT #2: nam=SQL*Net message to client ela= 1 driverid=1650815232 #bytes=1 p3=0 obj#=-1tim=1151519906035188WAIT #2: nam=SQL*Net message from client ela= 192driver id=1650815232 #bytes=1 p3=0 obj#=-1tim=1151519906035400STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op=FASTDUAL (cr=0 pr=0 pw=0 time=3 us)Trace fie
  5. 5. Step 3: ???Methodology• Identify Slow Queries• Look at Execution Plan• FixFix1. Analyze stats2. Go to step 1WTF??Fix If you are lucky, analyze for1. Column histograms2. Missing or better Indexes
  6. 6. Explain Plan: Like DirectionsWhere is the Map?
  7. 7. Explain Plan: Like DirectionsWhere is the Map?
  8. 8. Explain Plan: Like DirectionsWhere is the Map?
  9. 9. SQL Tuning1. Two Table Join2. Multi-Table Join3. Create Map4. Design Methodology5. Examples
  10. 10. How to Join two tables?1. Which table to start with• Hardest step ?2. What Indexes to use3. What type of join to use HJ, NLDesign options:• Partitions• IOT• Bitmap indexes• Hash cluster• Materialized views• etc
  11. 11. Two Table Join1. Index exist?2. Type of Relation• One to One• One to Many• Many to Many3. Special Cases• Outer Joins• Not Exists
  12. 12. Table Join Orderselect *from a, bwherea.id = b.idA Bid dataid dataEvery row visits Every rowWork= A-rows x B-rows (8 x 4 )HJ would optimizes to simulate index lookupIf No Index then (NL) order doesn’t matter
  13. 13. 2 Table join, with indexesselect *from a, bwherea.id = b.idA Bid datadata idWith IndexesStart with the least rows8
  14. 14. 2 Table join, with indexesselect *from a, bwherea.id = b.idA Bid datadata idWith IndexesStart with the least rowsB Adata id id data8 4
  15. 15. 2 table join - filtersselect *from a, bwherea.id = b.id -- joinand a.field = ‘val a’ -- filter aand b.field = ‘val b’ -- filter bABid datadata idStart on table with least rows after filter23
  16. 16. Two Table Joins – looks simpleA BInner Join
  17. 17. Two Table JoinsA BA BA BLeft join B B(+)Not exists BInner Join
  18. 18. Two Table JoinsA BA BA BA BA BLeft join B B(+)Not exists BRight join B A(+)Not Exists AInner Join
  19. 19. Two Table JoinsA BA BA BA B A BA BA BLeft join B B(+)Not exists BFull outer (union) Right join B A(+)Not Exists AUnion of Not ExistsInner JoinDoesn’t tell the wholestoryMissing « amplifications »
  20. 20. One to One - intersection12121 12 2A BA BBAMAP
  21. 21. One to Many - projection1122121 11 12 22 2BAA BA BMAP
  22. 22. 111111Many to Many - amplification1 11 11 11 11 11 11 11 1A BABA BMAPrA*rB-------------------------min(ndv(A),ndv(B))
  23. 23. Two Table JoinsA B A BLeft join B B(+) Right join B A(+)A BMAP MAPA Bo o
  24. 24. Two Table JoinsA BLeft join B B(+)Color nodes that return no dataSelect a.* from a, b where b.field(+) = a.field;A BVA BVMultiplieroo ?oPointless – join onB has no affect ifno B cols selectedVPointless – join onB has no affect ormultiplies rows fromA if no B colsselected
  25. 25. ExistsSELECT *FROM dept d WHERE exists ( SELECT null FROMemp e WHERE e.deptno=d.deptno);SELECT *FROM dept d WHERE d.deptno in( SELECT deptno FROM emp e );Select dept.* from emp, dept where emp.deptno=dept.deptno; /* can get duplicates */dept empEMAP
  26. 26. Not ExistsSELECT *FROM dept d WHERE not exists ( SELECTnull FROM emp e WHERE e.deptno=d.deptno);SELECT *FROM dept d WHERE d.deptno not in ( SELECTdeptno FROM emp e and deptno is not null );SELECT dept.* FROM dept LEFT OUTER JOIN empON dept.deptno = emp.deptno WHERE emp.deptno ISNULL;dept empNMAP
  27. 27. Two Table Join1. Where to start1. Generally start with the least rows after filtering withpredicate2. Drawing Map:– One to One / One to Many / Many to Many– Outer Joins / Not ExistsNow , three table joins:A BNA BoBA A B A B
  28. 28. Three table join1 row4 rows8 rowsEx) 1 customer 4 orders, each order has 2 order_lines each1 row1 row1 roworder_lines orders customerJoin directionJoin direction
  29. 29. Three table joinorder_lines orders customerFWhereorder_lines.field = valueA Filter on order_lines is going to eliminate workon orders and customers, if we start at order_lines
  30. 30. Three table joinorder_lines orders customerFWhereorder_lines.field = valueStarting with a filter on order_lines is going to eliminate work
  31. 31. Three table joinorder_lines orders customerFWhereorders.field = valueStarting with a Filter on orders is going to eliminate workThen Join to customers => keeps the number of rows the same12
  32. 32. Three table joinorder_lines orders customerFWherecustomer.field = valueStarting on a filter on customer is going to eliminate work
  33. 33. Three table joinorder_lines orders customerFFFWhat if a filter on all three?Choose the one that filter’s the highestpercent of the table.100% * (select count(*) from TAB where condition)---------------------------(select count(*) from Tab)
  34. 34. 4 or more table joinOracle can only join one table in at a time.Oracle can’t (normally) join two different sub-branches
  35. 35. Put it all together : VST1. Tables– drawn as nodes2. Joins :– drawn map connector lines• One-to-one, one-to-many, many-to-many• Exists, not exists, outer joins3. Filters– mark on each table with filter in where clause35 6/22/2013
  36. 36. How to VST: Tables and JoinsSELECT C.Phone_Number, C.Honorific, C.First_Name, C.Last_Name,C.Suffix, C.Address_ID, A.Address_ID, A.Street_Address_Line1,A.Street_Address_Line2, A.City_Name, A.State_Abbreviation,A.ZIP_Code, OD.Deferred_Shipment_Date, OD.Item_Count,ODT.Text, OT.Text, P.Product_Description, S.Shipment_DateFROM Orders O, Order_Details OD, Products P, Customers C, Shipments S,Addresses A, Code_Translations ODT, Code_Translations OTWHERE UPPER(C.Last_Name) LIKE :Last_Name||%AND UPPER(C.First_Name) LIKE :First_Name||%AND OD.Order_ID = O.Order_IDAND O.Customer_ID = C.Customer_IDAND OD.Product_ID = P.Product_ID(+)AND OD.Shipment_ID = S.Shipment_ID(+)AND S.Address_ID = A.Address_ID(+)AND O.Status_Code = OT.CodeAND OT.Code_Type = ORDER_STATUSAND OD.Status_Code = ODT.CodeAND ODT.Code_Type = ORDER_DETAIL_STATUSAND O.Order_Date > :Now - 366ORDER BY C.Customer_ID, O.Order_ID DESC, S.Shipment_ID, OD.Order_Detail_ID;TablesOrders O,Order_Details OD,Products P,Customers C,Shipments S,Addresses A,Code_Translations ODT,Code_Translations OTJoinsOD.Order_ID = O.Order_IDO.Customer_ID = C.Customer_IDOD.Product_ID = P.Product_ID(+)OD.Shipment_ID =S.Shipment_ID(+)S.Address_ID = A.Address_ID(+)O.Status_Code = OT.CodeOD.Status_Code = ODT.CodeDan Tow – SQL TUNINGFiltersWHERE UPPER(C.Last_Name) LIKE :Last_Name||%AND UPPER(C.First_Name) LIKE :First_Name||%AND OT.Code_Type = ORDER_STATUSAND O.Order_Date > :Now – 366AND ODT.Code_Type = ORDER_DETAIL_STATUS
  37. 37. Layout tables and connectionsTablesOrders O,Order_Details OD,Products P,Customers C,Shipments S,Addresses A,Code_Translations ODT,Code_Translations OTJoinsOD.Order_ID = O.Order_IDO.Customer_ID = C.Customer_IDOD.Product_ID = P.Product_ID(+)OD.Shipment_ID = S.Shipment_ID(+)S.Address_ID = A.Address_ID(+)O.Status_Code = OT.CodeOD.Status_Code = ODT.CodeFSAODPODTCOTODan Tow – SQL TUNING
  38. 38. UnstructuredCopyright 2006JoinsOD.Order_ID = O.Order_IDO.Customer_ID = C.Customer_IDOD.Product_ID = P.Product_ID(+)OD.Shipment_ID = S.Shipment_ID(+)S.Address_ID = A.Address_ID(+)O.Status_Code = OT.CodeOD.Status_Code = ODT.CodeNeater, but can you do anything with it?What’s the optimal execution path?SAODP ODTCOTO
  39. 39. Parents and ChildrenJoinsOD.Order_ID = O.Order_IDO.Customer_ID = C.Customer_IDOD.Product_ID = P.Product_ID(+)OD.Shipment_ID = S.Shipment_ID(+)S.Address_ID = A.Address_ID(+)O.Status_Code = OT.CodeOD.Status_Code = ODT.CodeODTODPCAOSOTPrimary Key (unique index)No index or non-uniqueMasterDetailStructurethetree
  40. 40. VST – filters and best path Filters help determine best pathParentChildParentChildConcept:1. Start at most selective filter2. Join down first, before joining upwardsFiltersWHERE UPPER(C.Last_Name) LIKE :Last_Name||%AND UPPER(C.First_Name) LIKE :First_Name||%AND OT.Code_Type = ORDER_STATUS‘AND ODT.Code_Type = ORDER_DETAIL_STATUSAND O.Order_Date > :Now – 366 FF30%0.02%100% * (select count(*) from TAB where condition)---------------------------(select count(*) from Tab)SAODP ODTC OTO
  41. 41. FF30%0.02%SAODP ODTC OTOVST – best pathFF
  42. 42. FF30%0.02%SAODP ODTC OTOVST – best pathFF/*+ Leading (C,O,OT, OD ) */Dan TowSQL TUNING
  43. 43. T9.6T4T1.3MT2T6 T7.001T10.5T11 T12.5T13.2T3T8.7T14.9T15.8T16T5
  44. 44. T9.6T4T1.3MT2T6 T7.001T10.5T11 T12.5T13.2T3T8.7T14.9T15.8T16T5T7 -> T13
  45. 45. T9.6T4T1.3MT2T6T10.5T11 T12.5T3T8.7T14.9T15.8T16T5T7 -> T13T7 ->T13
  46. 46. T9.6T4T1.3MT2T6T10.5T11T3T8.7T14.9T15.8T16T5T7 -> T13T7 ->T13-> T12
  47. 47. T9.6T4T1.3MT6T10.5T11T3T8.7T14.9T15.8T16T5T7 -> T13T7 ->T13-> T12 ->T2
  48. 48. T9.6T4T1.3MT10.5T11T3T8.7T14.9T15.8T16T5T7 -> T13T7, T13, T12, T2 , T6
  49. 49. T9.6T4T1.3MT11T3T8.7T14.9T15.8T16T5T7 -> T13T7, T13, T12, T2 , T6, T10
  50. 50. T9.6T4T1.3MT3T8.7T14.9T15.8T16T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11
  51. 51. T9.6T4T1.3MT3T8.7T14.9T16T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11,T15
  52. 52. T9.6T4T1.3MT3T8.7T14.9T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11,T15, T16
  53. 53. T9.6T4T1.3T3T8.7T14.9T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11,T15, T16, M
  54. 54. T9.6T4T3T8.7T14.9T5T7 -> T13T7, T13, T12, T2, T6, T10, T11, T15, T16,M, T1
  55. 55. T9.6T3T8.7T14.9T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11,T15, T16, M,T1, T4
  56. 56. T3T8.7T14.9T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11,T15, T16, M,T1, T4,T9
  57. 57. T5T7 -> T13T7, T13, T12, T2 , T6,T10, T11,T15, T16, M,T1,T4,T9,T3,T8T14
  58. 58. T7, T13, T12, T2 , T6,T10, T11,T15, T16, M,T1,T4,T9,T3,T8T14, T5Why not Guess ?For 17 table join, there are 355 Trillion combinations
  59. 59. CartesianSELECTA.BROKER_ID BROKER_ID,A.BROKER_LAST_NAME BROKER_LAST_NAME,A.BROKER_FIRST_NAME BROKER_FIRST_NAME,A.YEARS_WITH_FIRM YEARS_WITH_FIRM,C.OFFICE_NAME OFFICE_NAME,SUM (B.BROKER_COMMISSION)TOTAL_COMMISSIONSFROMBROKER A,CLIENT_TRANSACTION B,OFFICE_LOCATION C,INVESTMENT IWHEREA.BROKER_ID = B.BROKER_ID ANDA.OFFICE_LOCATION_ID =C.OFFICE_LOCATION_IDGROUP BYA.BROKER_ID,A.BROKER_LAST_NAME,A.BROKER_FIRST_NAME,A.YEARS_WITH_FIRM,C.OFFICE_NAME;
  60. 60. Implied Cartesianselectc.client_first_name, c.client_last_name,ct.action, ct.price,b.broker_last_name, b.broker_first_name,o.office_namefromclient_transaction ct,client c,broker b,office_location owherect.price > 100and b.broker_id=ct.broker_idand c.broker_id = b.broker_idand o.office_location_id = b.office_location_id
  61. 61. Diagram work for Many to OneWhat about many to many?
  62. 62. UnstructuredCopyright 2006JoinsOD.Order_ID = O.Order_IDO.Customer_ID = C.Customer_IDOD.Product_ID = P.Product_ID(+)OD.Shipment_ID = S.Shipment_ID(+)S.Address_ID = A.Address_ID(+)O.Status_Code = OT.CodeOD.Status_Code = ODT.CodeSAODP ODTC OTOSAODP ODTCOTO
  63. 63. Many-to-One vs Many-to-ManyPredicate Filter123B -> C -> A go to A or C?Now what?
  64. 64. Adding ConstraintsSELECT COUNT (*)FROMb,c,aWHEREb.val2 = 100 ANDa.val1 = b.id ANDb.val1 = c.id;58 logical readsalter table c add constraint c_pk unique (id);alter table b add constraint b_pk unique (id);7 logical reads
  65. 65. 10053BC$: 4#: 1$: 5428#: 59999A$: 92#: 999B A CB C AC A BC B AA C BA B CTable: A Alias: ABest:: AccessPath: TableScanCost: 92.18 Degree: 1Resp: 92.18 Card: 999.00Best:: AccessPath: IndexRangeIndex: B_V2Cost: 4.00 Degree: 1Resp: 4.00 Card: 1.00Best:: AccessPath: IndexFFSIndex: C_PK_CONCost: 35.57 Degree: 1Resp: 35.57 Card: 59999.00Join order[1]: B[B]#0 A[A]#1 C[C]#2***************Now joining: A[A]#1***************Best:: JoinMethod: NestedLoopCost: 6.00 Degree: 1 Resp: 6.00 Card: 1.00 Bytes: 16***************Now joining: C[C]#2***************Best:: JoinMethod: NestedLoopCost: 6.00 Degree: 1 Resp: 6.00 Card: 1.00 Bytes: 21***********************Best so far: Table#: 0 cost: 4.0020 card: 1.0000 bytes: 12Table#: 1 cost: 6.0031 card: 1.0000 bytes: 16Table#: 2 cost: 6.0032 card: 1.0000 bytes: 21alter session set events=10053 trace name context forever;
  66. 66. No Unique ConstraintA$: 75#: 999B A CNL: $: 10#: 1B AC$: 6$: 4#: 1$: 8NL:$: 18#: 1B C ANL: $: 10#: 1B CA$: 6.01$: 4#: 1$: 8C A BC B A A C B A B CA$: 75#: 999C$: 5428#: 59999C$: 5428#: 59999AB C BJoin order[6]: C[C]#2 A[A]#1 B[B]#0Join order aborted: cost > best plan cost$HJ: $: 10#: 1
  67. 67. Unique ConstraintA$: 75#: 999B A CNL: $: 10#: 1B AC$: 6$: 4#: 1$: 8NL:$: 18#: 1B C ANL: $: 10#: 1B CA$: 5$: 4#: 1$: 7C A BC B A A C B A B CA$: 75#: 999C$: 5428#: 59999C$: 5428#: 59999AB C BJoin order[6]: C[C]#2 A[A]#1 B[B]#0Join order aborted: cost > best plan cost$HJ: $: 10#: 1NL:$: 16#: 1
  68. 68. Diagraming: what to do with many to many• With many to many we don’t know which direction to go• How an we improve the diagram?• -> Add two table join result set sizes
  69. 69. Join sizesJoin SizesUse the Joinsizes todetermine pathof leastresistance
  70. 70. Look at 3 queries• Query 1 runs more than 24 hours• Query 2 outer joins and scalar sub-queries• Query 3 create path not available to Oracle
  71. 71. Query 1 : Over 24 hours to runSELECTA0.zuchinis,A0.brocoli,C0.OrangesFROM(SELECTA1.planted_date,A1.pears,A1.zuchinis,A1.brocoliFROMFOO.A A1,(SELECTzuchinis,brocoliFROM FOO.A A2WHEREpears = M ANDplanted_date + 0 >= ADD_MONTHS ((SELECTMAX (planted_date)FROM FOO.B B1WHEREpears = M),- 11)GROUP BYzuchinis,brocoliHAVING COUNT (*) = 12)i2WHEREA1.planted_date = (SELECTMAX (planted_date)FROM FOO.B B2WHEREpears = M) ANDA1.pears = M ANDA1.zuchinis = i2.zuchinis (+) ANDA1.brocoli = i2.brocoli (+)UNIONSELECTA4.planted_date,A4.pears,A4.zuchinis,A4.brocoliFROM FOO.A A4WHEREA4.planted_date >01-OCT-08 and A4.planted_date <03-OCT-08 ANDA4.pears = D ANDA4.green_beans = 1AND NOT EXISTS (SELECT*FROM FOO.A A5WHEREpears = M ANDplanted_date = (SELECTMAX (planted_date)FROM FOO.B B3WHEREpears = M) ANDA4.zuchinis = A5.zuchinis ANDA4.brocoli = A5.brocoli))b,FOO.A A0,FOO.C C0,FOO.D D0,FOO.E E0WHEREA0.planted_date >01-OCT-08 andA0.planted_date <03-OCT-08 ANDA0.pears = D ANDA0.green_beans = 1 ANDA0.zuchinis = b.zuchinis ANDA0.brocoli = b.brocoli ANDA0.planted_date = C0.planted_date ANDA0.pears = C0.pears ANDA0.zuchinis = C0.zuchinis ANDA0.brocoli = C0.brocoli ANDA0.planted_date = D0.planted_date ANDA0.pears = D0.pears ANDA0.harvest_size = D0.harvest_size ANDC0.Oranges = D0.Oranges ANDC0.apples = D0.apples AND(D0.lemons = 0 ORD0.lemons IS NULL) ANDA0.planted_date = E0.planted_date ANDA0.pears = E0.pears ANDA0.harvest_size = E0.harvest_size ANDC0.Oranges = E0.Oranges ANDC0.apples = E0.apples AND(E0.lemons = 0 ORE0.lemons IS NULL)ORDER BYA0.zuchinis, A0.brocoli;
  72. 72. Visual SQL Diagram9 secs
  73. 73. Default vs TunedDefaultTuned
  74. 74. Where is the map?
  75. 75. Comparing Plans : 24 hours to 5 minsNLNLNLNLHJHJNLNL
  76. 76. Q2SELECT CASE WHEN M.NYC IS NULL THEN (SELECT /*+ qb_name(qb1) */ MAX (Kona)FROM foo.FWHERE harvest_date = to_date(08/10/2008,dd/mm/yyyy)AND Argentina = TRIM (D) AND Norway = F_OUTER.NorwayELSE M.NYC END AS NYC,CASE WHEN F_OUTER.Perth IS NULL THEN NULLELSE (SELECT /*+ qb_name(qb2) */ Georgia FROM foo.PWHERE harvest_date = to_date(08/10/2008,dd/mm/yyyy)AND Argentina = TRIM (D) AND Paris = F_OUTER.Perth)END AS richard,CASE WHEN F_OUTER.Aruba IS NULL THEN NULLELSE (SELECT /*+ qb_name(qb3) */ Georgia FROM foo.PWHERE harvest_date = to_date(08/10/2008,dd/mm/yyyy)AND Argentina = TRIM (D) AND Paris = F_OUTER.Aruba)END AS Jody,CASE WHEN F_OUTER.Portland IS NULL THEN NULLELSE (SELECT /*+ qb_name(qb4) */ Georgia FROM foo.PWHERE harvest_date = to_date(08/10/2008,dd/mm/yyyy)AND Argentina = TRIM (D) AND Paris = F_OUTER.Portland)END AS TomFROM foo.F F_OUTER, foo.M , foo.J , foo.N ,(SELECT /*+ qb_name(qb5) */ H.SF, Oregon, H.Haiti, K.Bermuda, L.DenmarkFROM (foo.H LEFT OUTER JOIN foo.KON H.harvest_date = K.harvest_dateAND H.Argentina = K.Argentina AND H.SF = K.SFAND K.Dallas = 001)LEFT OUTER JOIN FOo.LON H.harvest_date = L.harvest_dateAND H.Argentina = L.Argentina AND H.SF = L.SFWHERE H.harvest_date = to_date(08/10/2008,dd/mm/yyyy)AND H.Argentina = TRIM (D)) extraWHERE F_OUTER.harvest_date = M.harvest_date(+)AND F_OUTER.Argentina = M.Argentina(+)AND F_OUTER.Norway = M.Norway(+)AND M.Norway(+) = M.Texas(+)AND F_OUTER.harvest_date = to_date(08/10/2008,dd/mm/yyyy)AND F_OUTER.Argentina = TRIM (D)AND M.harvest_date(+) = to_date(08/10/2008,dd/mm/yyyy)AND M.Argentina(+) = TRIM (D)AND F_OUTER.Norway = F_OUTER.HawaiiAND F_OUTER.harvest_date = J.harvest_date(+)AND F_OUTER.Argentina = J.Argentina(+)AND F_OUTER.Norway = J.Texas(+)AND J.harvest_date(+) = to_date(08/10/2008,dd/mm/yyyy)AND J.Argentina(+) = TRIM (D)AND F_OUTER.Iraq = extra.SF(+)AND F_OUTER.harvest_date = N.harvest_date(+)AND F_OUTER.Argentina = N.Argentina(+)AND F_OUTER.Norway = N.Hawaii(+)AND N.Jordon(+) = 0/
  77. 77. Scalar Sub-queries12825845682348
  78. 78. Q2The subqueries in the select clause look likeselect CASE WHEN F.f1 IS NULLTHEN NULLELSE (SELECT X.f2FROM XWHERE code_vl = F.f1)END AS f0from F;and should be merged into the query like:select CASE WHEN F.f1 IS NULLTHEN NULLELSE ( X.f2)END AS f0from F , Xwhere code_vl(+) = F.f1;select CASE WHEN F.f1 IS NULLTHEN NULLELSE (SELECT X.f2FROM XWHERE code_vl = F.f2)END AS f0from F;select CASE WHEN F.f1 IS NULLTHEN NULLELSE ( X.f2)END AS f0from F , Xwhere code_vl(+) = F.f1;
  79. 79. Q3SELECT DISTINCT *FROMFOO.a a, FOO.c c, FOO.d d, FOO.g gWHEREa.planted_date > 01-OCT-08 ANDa.planted_date < 03-OCT-08 ANDa.pears = D AND a.green_beans = 1 ANDa.planted_date = c.planted_date ANDa.pears = c.pears ANDa.zuchinis = c.zuchinis ANDa.brocoli = c.brocoli ANDa.planted_date = d.planted_date ANDa.pears = d.pears ANDa.harvest_size = d.harvest_size ANDc.oranges = d.oranges ANDc.apples = d.apples AND(d.lemons = 0 OR d.lemons IS NULL) ANDa.planted_date = g.planted_date ANDa.pears = g.pears ANDa.harvest_size = g.harvest_size ANDc.oranges = g.oranges ANDc.apples = g.apples AND(g.lemons = 0 OR g.lemons IS NULL) ANDa.zuchinis = 0236 ANDd.apples = g.apples ANDd.oranges = g.orangesORDER BY a.zuchinis, a.brocoli;
  80. 80. Q3: Transitivity81 6/22/20131,126,4027,136,362
  81. 81. Q382 6/22/2013SELECT * FROM(SELECT /*+ NO_MERGE */ c.apples, c.oranges, a.harvest_sizeFROM a, cWHEREa.planted_date = TO_DATE (02/10/2008, dd/mm/yyyy) ANDa.pears = D ANDa.green_beans = 1 ANDa.planted_date = c.planted_date ANDa.pears = c.pears ANDa.zuchinis = c.zuchinis ANDa.brocoli = c.brocoli ANDa.zuchinis = 0236) X,(SELECT /*+ NO_MERGE */ d.apples, d.oranges, d.harvest_sizeFROM d, gWHEREd.planted_date = TO_DATE (02/10/2008, dd/mm/yyyy) ANDg.planted_date = TO_DATE (02/10/2008, dd/mm/yyyy) ANDg.apples = d.apples ANDd.oranges = g.oranges ANDd.pears = D ANDg.pears = D ANDg.pears = d.pears ANDg.harvest_size = d.harvest_size AND(d.lemons = 0 OR d.lemons IS NULL) AND(g.lemons = 0 OR g.lemons IS NULL)) YWHEREX.oranges = Y.oranges ANDX.apples = Y.apples ANDX.harvest_size = Y.harvest_size;This final version runs inelapsed 0.33 secs and 12K logical readsdown from an originalelapsed 4.5 secs and 1M logical reads
  82. 82. HINTS• Leading (tab_alias , table_alias … ) 10g (9i use ORDERED, not as good )• USE_NL (table_alias) – Inner Table (2cd in xpla not driving)• USE_HASH (table_alias) – probe into (1st in xplan)• INDEX (tab_alias index_name)• NO_MERGEOracle first decides join order then join type(example http://www.adp-gmbh.ch/blog/2008/01/17.php)83 6/22/2013
  83. 83. FF30%0.02%SAODP ODTC OTOLeading Hint, use table alias (not table)FF/*+ Leading (C,O,OT, OD ) */
  84. 84. HJXY Hash XresultsYNLXY YXselect /*+ LEADING(X,Y) USE_HASH(Y) */ *select /*+ LEADING(X,Y) USE_NL(Y) */ *
  85. 85. What tools to use to create VST diagrams?• Paper– Modifications messy and difficult• PowerPoint– Can move things around– Sticky connectors– Easy to modify• DB Optimizer– Automatic and still modifiable
  86. 86. VST Steps Summary1.Diagram tables2.Draw connectors for each join3.Calculate filter ratio1.If many to many thencalculate two table join sizesExecution Path• Start at the most selective join filter• Join to keep the running result set size smallMany to Many relationships = problems6/22/2013ParentChildParentChildFF30%0.02%SAODP ODTC OTO
  87. 87. SELECTO.ORDER_ID,LINE_ITEM_ID,PRODUCT_ID,UNIT_PRICE,QUANTITY,ORDER_MODE,ORDER_STATUS,ORDER_TOTAL,SALES_REP_ID,PROMOTION_ID,C.CUSTOMER_ID,CUST_FIRST_NAME,CUST_LAST_NAME,CREDIT_LIMIT,CUST_EMAIL,ORDER_DATEFROMORDERS O,ORDER_ITEMS OI,CUSTOMERS CWHEREO.ORDER_ID = OI.ORDER_ID ANDO.CUSTOMER_ID = C.CUSTOMER_ID ANDO.ORDER_STATUS <= 4VST vs Explain PlanMJ FF
  88. 88. Graphical Explain Plan
  89. 89. Visual SQL Tuning (VST)Table SizesJoin SizesFilter RatiosExists
  90. 90. Execution Plan
  91. 91. Summary1.Database - AAS– Profile database– Use wait interface and graphics– Identify machine, application, database or SQL2.SQL - VST– Indexes, stats, execution path– Visual SQL Tuning
  92. 92. END
  93. 93. View Expansion
  94. 94. View Expansion
  95. 95. Types of Subqueries• subquery– query in where clause– Select 1 from dual where 1 = (select 1 from dual);• correlated subquery– Subquery uses fields from outer query– Select 1 from dual a where 1=(select 1 from dual b wherea.dummy=b.dummy)• scalar subquery– Query in select list– Returns 1 value or null , ie scalar– Select (select 1 from dual) from dual;• inline views– Query in from clause– Select 1 from dual a, (select 1 from dual ) b;
  96. 96. Visual SQL Tuning
  97. 97. • Layout tables Graphically– Details tables above Masters– One to one relations side by side– Many to many any which wayMany tosingle value
  98. 98. Join Set SizesJoin type max result set sizepossiblenotesone-to-scalar A this is equivalent to a filter on Atable B returns one value like a max(), min(),count() etcone-to-one min(rA,rB)one-to-many rAJoining from A to B will not increase the result setsizemany-to-many rA*rB-------------------------min(ndv(A),ndv(B))The more duplicates in both tables the greaterchancethe result set size will explode99 6/22/2013We can say a lot about the join set size between two tables just by thejoin type and the number of rows in the table and NDV in the join column,but the easiest way most often is just to extract the two table joins andrun a count(*) on that subset of the query
  99. 99. Join Filter ratiosAB Jm=1Jd ~> 1FKPKAB Jm <= 1Jd ~> 1detailMasterUniqueindex oruniqueconstraintJd, = join detail ratio , the avg number of rows returned when joining from the master to childJm = master join ratio, the avg number of rows returned joining from the child into the master.Jm = 1 when PK/FK relations,Jm < 1 possible when unique indexes or unique constraints instead of PK/FK.Jd < 1 rare but acts as filter instead of a multiplier
  100. 100. Hash Join vs NLCol ACol BCol C Filter &Join IndexCol DTable YTable XFilter IndexJoin IndexCol ACol BCol CFilter IndexJoin IndexCol DTable YTable XFilter IndexJoin IndexNL HJDriving Table (smaller set)Drive from Table Y off of set of rowsreturned from filter on column CNested loops into Table X on Index onJoinFilter results without Index even thoughindex on filter columnCreate hash result set on Table Y fromfilter on column CProbe hash result set with rows fromfilter on table X on column AFilter IndexJoin IndexBuild Hash TableProbe Hash TableNLXYHJXY
  101. 101. Left Deep HJHJHJHJT1T2T3T4T1 T2T3T4HJHJHJT1 T2T3HashedHashed probeprobeT4probeHashed
  102. 102. Right Deep HJHJT4HJT3HJT2T1T2 T1T3T4HJHJHJT2 T1T3T4probehashedhashedhashedprobeprobe
  103. 103. Nest Loops left deepT1 T2T3T4NLNLNLT1T2T3T4NLNLNLprobedprobedprobed
  104. 104. Nest Loops can’t be right deepT3 T4T2T1 NLT1NLT2NLT3T4probedprobedprobedNLNLNL
  105. 105. BushyT1 T2HJNLT1T2NLT3T4NLT3 T4NLHJselect t3id, a.*, b.* from( select /*+ no_merge */t2.id t2id, t1.data t1data, t2.data t2datafrom t1, t2where t1.id = t2.id ) a,( select /*+ no_merge */t3.id t3id, t3.data t3data, t4.data t4datafrom t3, t4where t3.id = t4.id ) bwhere a.t2id=b.t3id/

×