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.

Transformations - how Oracle rewrites your statements

Before Oracle optimises your statement it may apply transformations that restructure it completely. This presentation examines the optimiser’s capabilities in transforming SQL. It describes performance issues that are overcome by common transformations, and more importantly identifies common code techniques which cannot be transformed and which may cause performance problems. It aims to clarify the reality for developers who now frequently just say "I can write what I like as Oracle will rewrite it for me anyway".

  • Be the first to comment

Transformations - how Oracle rewrites your statements

  1. 1. www.sagecomputing.com.au penny@sagecomputing.com.au Transformations – how Oracle rewrites your statements Penny Cookson SAGE Computing Services SAGE Computing Services Customised Oracle Training Workshops and Consulting
  2. 2. Agenda How to identify transformations Join Factorisation Join Elimination Other Transformations Effect on Parse Time Queries in the Select
  3. 3. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 10g: ALTER SYSTEM FLUSH SHARED_POOL; ALTER SESSION SET TRACEFILE_IDENTIFIER = ‘events_10053_1’; ALTER SESSION SET EVENTS ‘10053 trace name context forever’;
  4. 4. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 10g: Parse the statement:- SELECT * FROM organisations WHERE postcode = 6000 View the trace file ALTER SESSION SET EVENTS ‘10053 trace name context off’
  5. 5. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 11g: ALTER SYSTEM FLUSH SHARED_POOL; ALTER SESSION SET TRACEFILE_IDENTIFIER = ‘events_10053_2’; ALTER SESSION SET EVENTS ‘trace[rdbms.SQL_Optimizer.*][sql:40038fgx69y23]’;
  6. 6. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 11g: Execute the statement:- SELECT * FROM organisations WHERE postcode = 6000; View the trace file ALTER SESSION SET EVENTS ‘trace[rdbms.SQL_Optimizer.*] off’;
  7. 7. Identifying Transformations – Tracing the Optimizer’s decisions More examples: ALTER SESSION SET EVENTS ‘trace[rdbms.SQL_Transform.*][sql:40038fgx69y23]’; Trace file smaller Transformations, session optimizer settings and bug fixes only
  8. 8. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 11g using DBMS_SQL_DIAG: Automatically hard parse the statement BEGIN dbms_sqldiag.dump_trace (p_sql_id => '40038fgx69y23' ,p_child_number => 0 ,p_component => 'Compiler' ,p_file_id => 'events_10053_4'); END; / View the trace file dbmsdiag.sql
  9. 9. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 11g using DBMS_SQL_DIAG: Is bind aware DECLARE v2 number; cursor c1 (p_code in resources.code%type) is SELECT /*+BIND_AWARE */ COUNT(l.quantity) FROM train1.bookings_large l WHERE resource_code = p_code; BEGIN open c1 ('PC2'); fetch c1 into v2; close c1; open c1 ('BRLG'); fetch c1 into v2; close c1; END; /
  10. 10. Identifying Transformations – Tracing the Optimizer’s decisions Oracle 11g using DBMS_SQL_DIAG: Is bind aware BEGIN dbms_sqldiag.dump_trace (p_sql_id => '463fjw7fvwmq6' ,p_child_number => 0 ,p_component => 'Compiler' ,p_file_id => 'events_10053_11'); END; / BEGIN dbms_sqldiag.dump_trace (p_sql_id => '463fjw7fvwmq6' ,p_child_number => 1 ,p_component => 'Compiler' ,p_file_id => 'events_10053_12'); END; / View the 11 trace file View the 12 trace file
  11. 11. Join Factorization TABLE_A TABLE_A TABLE_B TABLE_B TABLE_C TABLE_D UNION ALL
  12. 12. Join Factorization TABLE_A TABLE_B TABLE_B TABLE_C TABLE_D UNION ALL
  13. 13. Join Factorization alter session set optimizer_features_enable = '11.1.0.7' SELECT e.description, b.booking_no, b.cost FROM events_large e, bookings_large b, internal_organisations oi WHERE e.event_no = b.event_no AND e.org_id = oi.org_id AND oi.state = 'WA' UNION ALL SELECT e.description, b.booking_no, b.cost FROM events_large e, bookings_large b, external_organisations oe WHERE e.event_no = b.event_no AND e.org_id = oe.org_id AND oe.state = 'WA'
  14. 14. Version 11.1
  15. 15. Join Factorization alter session set optimizer_features_enable = '11.2.0.3' SELECT e.description, b.booking_no, b.cost FROM events_large e, bookings_large b, internal_organisations oi WHERE e.event_no = b.event_no AND e.org_id = oi.org_id AND oi.state = 'WA' UNION ALL SELECT e.description, b.booking_no, b.cost FROM events_large e, bookings_large b, external_organisations oe WHERE e.event_no = b.event_no AND e.org_id = oe.org_id AND oe.state = 'WA'
  16. 16. Join Factorization
  17. 17. Manual Join Factorization alter session set optimizer_features_enable = '11.1.0.7' SELECT evt.description, b.booking_no, b.cost FROM bookings_large b, (SELECT e.description, e.event_no FROM events_large e, internal_organisations oi WHERE e.org_id = oi.org_id AND oi.state = 'WA' UNION ALL SELECT e.description, e.event_no FROM events_large e, external_organisations oe WHERE e.org_id = oe.org_id AND oe.state = 'WA') evt WHERE evt.event_no = b.event_no
  18. 18. Manual Join Factorization
  19. 19. How to Avoid Stuffing It Up UNION (RATHER THAN UNION ALL) DISTINCT OUTER JOINS
  20. 20. Join Factorization – This is OK TABLE_A TABLE_A TABLE_B TABLE_B TABLE_C TABLE_D UNION ALL (+) (+)
  21. 21. Join Factorization – This is not OK TABLE_A TABLE_A TABLE_B TABLE_B TABLE_C TABLE_D UNION ALL (+) (+) (+) (+)
  22. 22. Join Elimination Oracle will get rid of joined tables if: We give it indexes it can use instead The PK and/or FK relationships imply a table is not required
  23. 23. Its done this for a long time SELECT b.booking_no, b.resource_code FROM bookings_large b, events_large e WHERE b.event_no = e.event_no AND e.contact_name like 'JOSIE%'
  24. 24. Why constraints are a good idea SELECT e.description FROM events e, organisations o WHERE e.org_id = o.org_id Constraints matter – they tell the optimiser stuff
  25. 25. Without a foreign key constraint SELECT e.description FROM events e, organisations o WHERE e.org_id = o.org_id ALTER TABLE events DISABLE CONSTRAINT org_fk
  26. 26. Without a foreign key constraint
  27. 27. Use RELY for Warehouses SELECT e.description FROM events e, organisations o WHERE e.org_id = o.org_id ALTER TABLE events MODIFY CONSTRAINT org_fk RELY;
  28. 28. Join Elimination - this is also OK SELECT e.description, o.org_id FROM events e, organisations o WHERE e.org_id = o.org_id
  29. 29. This won’t do join elimination SELECT e.description FROM event_state e, org_state o WHERE e.org_id = o.org_id AND e.state = o.state
  30. 30. Multi column primary keys don’t do Join Elimination SELECT e.description FROM event_state e, org_state o WHERE e.org_id = o.org_id AND e.state = o.state SELECT * FROM user_cons_columns WHERE constraint_name = 'EVTST_ORG_FK'
  31. 31. Multi column primary keys don’t do Join Elimination SELECT e.description FROM event_state e, org_state o WHERE e.org_id = o.org_id SELECT * FROM user_cons_columns WHERE constraint_name = 'EVTST_ORG_FK' Use artificial sequence numbers for Primary Keys
  32. 32. Join Elimination So who would write that rubbish? Useful with views where lots of columns are included but not all selected from the view Means views with a whole load of unnecessary stuff are not so bad now And we have View Merging transformations
  33. 33. CREATE VIEW pretty_stuff_for_users AS SELECT o.org_id, o.name, e.event_no, e.description event_description, e.start_date, r.description resource_description, b.booking_no, b.cost, b.quantity, b.resource_code FROM organisations o, events e, bookings b, resources r WHERE o.org_id = e.org_id AND e.event_no = b.event_no AND b.resource_code = r.code
  34. 34. SELECT booking_no, cost, quantity, resource_code, resource_description FROM pretty_stuff_for_users
  35. 35. SELECT e.description FROM events e, organisations o WHERE e.org_id = o.org_id
  36. 36. ALTER TABLE events modify (org_id not null) SELECT booking_no, cost, quantity, resource_code, resource_description FROM pretty_stuff_for_users
  37. 37. Join Factorization
  38. 38. Join Factorization
  39. 39. If a column is not null define it as NOT NULL
  40. 40. 10G – JOIN before the GROUP BY
  41. 41. 11G – GROUP BY before the JOIN
  42. 42. 10G – NOT IN (PROMISE_NO NULLABLE)
  43. 43. 10G – KILLED AFTER 1 hr
  44. 44. 11G – Rewrite as Null Aware Anti join
  45. 45. 10G – Full Outer Join – default behaviour
  46. 46. From version 10.2.0.3 SELECT /*+ NATIVE_FULL_OUTER_JOIN */ count(e.comments) nume, count (b.comments) numb FROM events_large e FULL OUTER JOIN bookings_large b ON (e.event_no = b.event_no) 10G – Full Outer Join – hint
  47. 47. 11G Native Full Outer Join
  48. 48. SELECT b.booking_no, b.cost, b.quantity, (SELECT description FROM resources r WHERE r.code = b.resource_code) FROM bookings_large b) SELECT b.booking_no, b.cost, b.quantity, r.description FROM bookings_large b, resources r WHERE b.resource_code = r.code This is fine and will actually be more efficient than this (but may have a different result) Queries in the SELECT
  49. 49. SELECT b.booking_no, b.cost, b.quantity, (SELECT description FROM resources r WHERE r.code = b.resource_code), (SELECT type_code FROM resources r WHERE r.code = b.resource_code), (SELECT daily_rate FROM resources r WHERE r.code = b.resource_code) FROM bookings_large b) This is really stupid and will access the RESOURCES table multiple times Queries in the SELECT
  50. 50. SELECT b.booking_no, b.cost, b.quantity, booking_utl.get_stat1 ( (SELECT description FROM resources r WHERE r.code = b.resource_code), (SELECT type_code FROM resources r WHERE r.code = b.resource_code), (SELECT daily_rate FROM resources r WHERE r.code = b.resource_code)), booking_utl.get_stat2 ( (SELECT description FROM resources r WHERE r.code = b.resource_code), (SELECT type_code FROM resources r WHERE r.code = b.resource_code), (SELECT daily_rate FROM resources r WHERE r.code = b.resource_code)), FROM bookings_large b) From a real example!!!
  51. 51. Much More Query Transformation SELECT e.event_no, e.start_date, sum(cost) totcost FROM events_large e, bookings_large b WHERE e.event_no = b.event_no GROUP BY e.event_no, e.start_date
  52. 52. Oracle 10g – Run a whole load of random statements – all of which require parsing
  53. 53. Oracle 11g – Run a whole load of random statements – all of which require parsing So Tuning the Shared Pool becomes more important, but overall the 11g CBO is pretty smart
  54. 54. Conclusion Proper relational database design techniques are important Views are OK 11g will do stuff 10g can’t – get rid of the hints Developer are encouraged to do stupid stuff Proper use of the shared pool is important
  55. 55. SAGE Computing Services Customised Oracle Training Workshops and Consulting Questions? www.sagecomputing.com.au penny@sagecomputing.com.au

×