zen and the art of SQL optimization Karen Morton
 
 
Simplicity
“ Make everything as simple as possible but no simpler. ” Albert Einstein
 
 
“ Normally, we do not so much look at things as   overlook them.” Alan Watts
simple vs simple-minded
Oracle 9.2.0.6 SELECT to_char(   to_date(:B1,‘DD-MON-YYYY’)+1,   ‘DD-MON-YYYY’ )   FROM dual;
What about its effect?
32.9% % of total R
1,087,770 # of executions
3,263,033 # of LIOs
v_date_str :=  to_char(   to_date( :B1,‘DD-MON-YYYY’ ) + 1,   ‘ DD-MON-YYYY’ ) ;
Focus
ETCIBMVIPNASAFBI
ETC IBM VIP NASA FBI
SELECT rowid, load_no, load_status, manifest_no, manifest_date FROM cs_loads  WHERE load_no = 552888 ; VARCHAR2(15) SELECT rowid, load_no, load_status, manifest_no, manifest_date FROM cs_loads  WHERE  load_no = 552888  ; datatype mismatch causes FULL SCAN SELECT rowid, load_no, load_status, manifest_no, manifest_date FROM cs_loads  WHERE load_no =‘552888’;
SELECT rowid, load_no, load_status, manifest_no, manifest_date FROM cs_loads  WHERE load_no = :B1 ;
Keys to Optimizing SQL
Tune the question, not the query.
What output should the query provide?
What special conditions need to be handled?
“ If you don’t know where you are going, you’ll end up somewhere else.” Yogi Berra
Reduce. Reuse.
Decrease row source sizes quickly
Access objects once and reuse the result set
“ Not enough gets said about the importance of abandoning crap.”   - Ira Glass
Practice.
Never stop learning
Stay connected
Think in sets
Test Test Test (then test again)
 
“ Practice, practice, practice. Until it becomes your practice.” Unknown
Going Zen
1
SELECT invoice_id, distribution_line_number  FROM ap.ap_invoice_distributions_all ap2  WHERE ap2.project_id > 0  AND ap2.pa_addition_flag = 'T'  MINUS  SELECT invoice_id, distribution_line_number  FROM ap.ap_invoice_distributions_all ap,  pa.pa_cost_distribution_lines_all pa  WHERE ap.project_id > 0  AND ap.pa_addition_flag = 'T'  AND pa.system_reference2 IS NOT NULL  AND TO_NUMBER(pa.system_reference2) = ap.invoice_id  AND TO_NUMBER(pa.system_reference3) = ap.distribution_line_number  ORDER BY invoice_id;  Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:20.09  60,941  57,116  6
SELECT invoice_id, distribution_line_number FROM (SELECT invoice_id, distribution_line_number, system_reference2, system_reference3 FROM ap.ap_invoice_distributions_all ap, (SELECT TO_NUMBER(system_reference2) system_reference2, TO_NUMBER(system_reference3) system_reference3 FROM pa.pa_cost_distribution_lines_all WHERE system_reference2 IS NOT NULL) WHERE system_reference2 (+) = ap.invoice_id AND system_reference3 (+) = ap.distribution_line_number AND ap.project_id > 0 AND ap.pa_addition_flag = 'T' ) WHERE system_reference2 IS NULL AND system_reference3 IS NULL ORDER BY invoice_id; Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:03.09  1,824  453  6
2
SELECT t.* FROM RMS.tasks t, RMS.status s WHERE t.status_id = s.id AND (EXISTS ( SELECT null FROM RMS.tasks ta, RMS.resources r    WHERE t.id = ta.parent_task_id AND ta.project_code = :p   AND ta.task_type_code = 'A' AND ta.resource_id = r.id   AND r.reporting_id = :r )    OR (t.project_code = :p AND  t.task_type_code = 'T') ); Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:09.50  287,330  992  3
SELECT t.* FROM RMS.tasks t, RMS.status s WHERE t.status_id = s.id AND EXISTS    (SELECT null FROM RMS.tasks ta,RMS.resources r    WHERE t.id = ta.parent_task_id AND ta.project_code = :p  AND ta.task_type_code = 'A' AND ta.resource_id = r.id  AND r.reporting_id = :r ) UNION SELECT t.* FROM RMS.tasks t, RMS.status s WHERE t.status_id = s.id AND t.id IN  (SELECT t.parent_task_id FROM RMS.tasks t, RMS.status s    WHERE t.status_id = s.id AND EXISTS (SELECT null FROM RMS.tasks ta, RMS.resources r    WHERE t.id = ta.parent_task_id AND ta.project_code = :p    AND ta.task_type_code = 'A' AND ta.resource_id = r.id    AND r.reporting_id = :r ); Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:00.01  128  0  3
3
SELECT J.emplid, J.empl_rcd, J.effdt, J.effseq  FROM PS_JOB J  WHERE J.effdt = (SELECT MAX(effdt) FROM PS_JOB    WHERE emplid = J.emplid   AND empl_rcd = J.empl_rcd   AND effdt <= SYSDATE )  AND J. effseq = (SELECT MAX(effseq) FROM PS_JOB    WHERE emplid = J.emplid    AND empl_rcd = J.empl_rcd    AND effdt = J.effdt ) ; Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:08.04  337,908  0  30,107
SELECT J.emplid, J.empl_rcd, J.effdt, J.effseq  FROM  (SELECT J.emplid, J.empl_rcd, J.effdt, J.effseq, MAX(J.effdt)    OVER (PARTITION BY J.emplid, J.empl_rcd ) max_effdt,  LAST_VALUE(J.effseq) OVER (PARTITION BY J.emplid, J.empl_rcd ORDER BY J.efdt, J.effseq ROWS BETWEEN CURRENT ROW AND    UNBOUNDED FOLLOWING ) max_effseq   FROM PS_JOB J  WHERE J.effdt <= SYSDATE ) J  WHERE J.effdt = J.max_effdt AND J.effseq = J.max_effseq; Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:00.44  1,009  0  30,107
4
SELECT utrsotp_desc FROM utrsotp, ucbsvco WHERE ucbsvco_sotp_code = utrsotp_code AND ucbsvco_dispatch_date = (SELECT MAX(ucbsvco_dispatch_date) FROM ucbsvco WHERE ucbsvco_cust_code = 1320908 AND ucbsvco_prem_code = '507601' AND ucbsvco_stus_code = 'C' AND ucbsvco_dispatch_ind IS NOT NULL) AND ucbsvco_stus_code = 'C' AND ucbsvco_dispatch_ind IS NOT NULL Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:20.16  106,693  0  1
SELECT utrsotp_desc FROM utrsotp, (SELECT ucbsvco_sotp_code, ucbsvco_dispatch_date, MAX(ucbsvco_dispatch_date) OVER(PARTITION BY    ucbsvco_cust_code, ucbsvco_prem_code) max_dispatch_dt FROM ucbsvco WHERE ucbsvco_cust_code = 1320908 AND ucbsvco_prem_code = '507601' AND ucbsvco_stus_code = 'C' AND ucbsvco_dispatch_ind IS NOT NULL) svco WHERE svco.ucbsvco_dispatch_date = svco.max_dispatch_dt AND svco.ucbsvco_sotp_code = utrsotp_code Elapsed Time  LIO Blocks  PIO Blocks  Total Rows ------------  ----------  ----------  ----------   00:00:00.18  15  0  1
 
Simplicity is powerful…
… but it is neither simple nor easy to achieve.
It is obtained  through the careful reduction of the nonessential.
While simplicity is the goal…
… it is possible to be “too simple.”
Your job is to find the balance most appropriate to your situation.
Thank You
http://www.method-r.com http://karenmorton.blogspot.com [email_address]

zen and the art of SQL optimization

  • 1.
    zen and theart of SQL optimization Karen Morton
  • 2.
  • 3.
  • 4.
  • 5.
    “ Make everythingas simple as possible but no simpler. ” Albert Einstein
  • 6.
  • 7.
  • 8.
    “ Normally, wedo not so much look at things as overlook them.” Alan Watts
  • 9.
  • 10.
    Oracle 9.2.0.6 SELECTto_char( to_date(:B1,‘DD-MON-YYYY’)+1, ‘DD-MON-YYYY’ ) FROM dual;
  • 11.
  • 12.
    32.9% % oftotal R
  • 13.
    1,087,770 # ofexecutions
  • 14.
  • 15.
    v_date_str := to_char( to_date( :B1,‘DD-MON-YYYY’ ) + 1, ‘ DD-MON-YYYY’ ) ;
  • 16.
  • 17.
  • 18.
    ETC IBM VIPNASA FBI
  • 19.
    SELECT rowid, load_no,load_status, manifest_no, manifest_date FROM cs_loads WHERE load_no = 552888 ; VARCHAR2(15) SELECT rowid, load_no, load_status, manifest_no, manifest_date FROM cs_loads WHERE load_no = 552888 ; datatype mismatch causes FULL SCAN SELECT rowid, load_no, load_status, manifest_no, manifest_date FROM cs_loads WHERE load_no =‘552888’;
  • 20.
    SELECT rowid, load_no,load_status, manifest_no, manifest_date FROM cs_loads WHERE load_no = :B1 ;
  • 21.
  • 22.
    Tune the question,not the query.
  • 23.
    What output shouldthe query provide?
  • 24.
    What special conditionsneed to be handled?
  • 25.
    “ If youdon’t know where you are going, you’ll end up somewhere else.” Yogi Berra
  • 26.
  • 27.
    Decrease row sourcesizes quickly
  • 28.
    Access objects onceand reuse the result set
  • 29.
    “ Not enoughgets said about the importance of abandoning crap.” - Ira Glass
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
    Test Test Test(then test again)
  • 35.
  • 36.
    “ Practice, practice,practice. Until it becomes your practice.” Unknown
  • 37.
  • 38.
  • 39.
    SELECT invoice_id, distribution_line_number FROM ap.ap_invoice_distributions_all ap2 WHERE ap2.project_id > 0 AND ap2.pa_addition_flag = 'T' MINUS SELECT invoice_id, distribution_line_number FROM ap.ap_invoice_distributions_all ap, pa.pa_cost_distribution_lines_all pa WHERE ap.project_id > 0 AND ap.pa_addition_flag = 'T' AND pa.system_reference2 IS NOT NULL AND TO_NUMBER(pa.system_reference2) = ap.invoice_id AND TO_NUMBER(pa.system_reference3) = ap.distribution_line_number ORDER BY invoice_id; Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:20.09 60,941 57,116 6
  • 40.
    SELECT invoice_id, distribution_line_numberFROM (SELECT invoice_id, distribution_line_number, system_reference2, system_reference3 FROM ap.ap_invoice_distributions_all ap, (SELECT TO_NUMBER(system_reference2) system_reference2, TO_NUMBER(system_reference3) system_reference3 FROM pa.pa_cost_distribution_lines_all WHERE system_reference2 IS NOT NULL) WHERE system_reference2 (+) = ap.invoice_id AND system_reference3 (+) = ap.distribution_line_number AND ap.project_id > 0 AND ap.pa_addition_flag = 'T' ) WHERE system_reference2 IS NULL AND system_reference3 IS NULL ORDER BY invoice_id; Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:03.09 1,824 453 6
  • 41.
  • 42.
    SELECT t.* FROMRMS.tasks t, RMS.status s WHERE t.status_id = s.id AND (EXISTS ( SELECT null FROM RMS.tasks ta, RMS.resources r WHERE t.id = ta.parent_task_id AND ta.project_code = :p AND ta.task_type_code = 'A' AND ta.resource_id = r.id AND r.reporting_id = :r ) OR (t.project_code = :p AND t.task_type_code = 'T') ); Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:09.50 287,330 992 3
  • 43.
    SELECT t.* FROMRMS.tasks t, RMS.status s WHERE t.status_id = s.id AND EXISTS (SELECT null FROM RMS.tasks ta,RMS.resources r WHERE t.id = ta.parent_task_id AND ta.project_code = :p AND ta.task_type_code = 'A' AND ta.resource_id = r.id AND r.reporting_id = :r ) UNION SELECT t.* FROM RMS.tasks t, RMS.status s WHERE t.status_id = s.id AND t.id IN (SELECT t.parent_task_id FROM RMS.tasks t, RMS.status s WHERE t.status_id = s.id AND EXISTS (SELECT null FROM RMS.tasks ta, RMS.resources r WHERE t.id = ta.parent_task_id AND ta.project_code = :p AND ta.task_type_code = 'A' AND ta.resource_id = r.id AND r.reporting_id = :r ); Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:00.01 128 0 3
  • 44.
  • 45.
    SELECT J.emplid, J.empl_rcd,J.effdt, J.effseq FROM PS_JOB J WHERE J.effdt = (SELECT MAX(effdt) FROM PS_JOB WHERE emplid = J.emplid AND empl_rcd = J.empl_rcd AND effdt <= SYSDATE ) AND J. effseq = (SELECT MAX(effseq) FROM PS_JOB WHERE emplid = J.emplid AND empl_rcd = J.empl_rcd AND effdt = J.effdt ) ; Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:08.04 337,908 0 30,107
  • 46.
    SELECT J.emplid, J.empl_rcd,J.effdt, J.effseq FROM (SELECT J.emplid, J.empl_rcd, J.effdt, J.effseq, MAX(J.effdt) OVER (PARTITION BY J.emplid, J.empl_rcd ) max_effdt, LAST_VALUE(J.effseq) OVER (PARTITION BY J.emplid, J.empl_rcd ORDER BY J.efdt, J.effseq ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) max_effseq FROM PS_JOB J WHERE J.effdt <= SYSDATE ) J WHERE J.effdt = J.max_effdt AND J.effseq = J.max_effseq; Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:00.44 1,009 0 30,107
  • 47.
  • 48.
    SELECT utrsotp_desc FROMutrsotp, ucbsvco WHERE ucbsvco_sotp_code = utrsotp_code AND ucbsvco_dispatch_date = (SELECT MAX(ucbsvco_dispatch_date) FROM ucbsvco WHERE ucbsvco_cust_code = 1320908 AND ucbsvco_prem_code = '507601' AND ucbsvco_stus_code = 'C' AND ucbsvco_dispatch_ind IS NOT NULL) AND ucbsvco_stus_code = 'C' AND ucbsvco_dispatch_ind IS NOT NULL Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:20.16 106,693 0 1
  • 49.
    SELECT utrsotp_desc FROMutrsotp, (SELECT ucbsvco_sotp_code, ucbsvco_dispatch_date, MAX(ucbsvco_dispatch_date) OVER(PARTITION BY ucbsvco_cust_code, ucbsvco_prem_code) max_dispatch_dt FROM ucbsvco WHERE ucbsvco_cust_code = 1320908 AND ucbsvco_prem_code = '507601' AND ucbsvco_stus_code = 'C' AND ucbsvco_dispatch_ind IS NOT NULL) svco WHERE svco.ucbsvco_dispatch_date = svco.max_dispatch_dt AND svco.ucbsvco_sotp_code = utrsotp_code Elapsed Time LIO Blocks PIO Blocks Total Rows ------------ ---------- ---------- ---------- 00:00:00.18 15 0 1
  • 50.
  • 51.
  • 52.
    … but itis neither simple nor easy to achieve.
  • 53.
    It is obtained through the careful reduction of the nonessential.
  • 54.
  • 55.
    … it ispossible to be “too simple.”
  • 56.
    Your job isto find the balance most appropriate to your situation.
  • 57.
  • 58.