Transformations - how Oracle rewrites your statements

Post on 16-Aug-2015

23 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

Transcript

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

Agenda

How to identify transformations

Join Factorisation

Join Elimination

Other Transformations

Effect on Parse Time

Queries in the Select

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’;

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’

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]’;

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’;

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

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

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;

/

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

ALTER SESSION

SET EVENTS ‘trace[rdbms.SQL_Optimizer.*] off’;

Join Factorization

TABLE_A

TABLE_A

TABLE_B

TABLE_B

TABLE_C

TABLE_D

UNION ALL

Join Factorization

TABLE_A

TABLE_B

TABLE_B

TABLE_C

TABLE_D

UNION ALL

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'

Version 11.1

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'

Join Factorization

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

Manual Join Factorization

How to Avoid Stuffing It Up

UNION (RATHER THAN UNION ALL)

DISTINCT

OUTER JOINS

Join Factorization – This is OK

TABLE_A

TABLE_A

TABLE_B

TABLE_B

TABLE_C

TABLE_D

UNION ALL

(+)

(+)

Join Factorization – This is not OK

TABLE_A

TABLE_A

TABLE_B

TABLE_B

TABLE_C

TABLE_D

UNION ALL

(+)

(+)

(+)

(+)

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

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%'

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

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

Without a foreign key constraint

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;

Join Elimination - this is also OK

SELECT e.description, o.org_id

FROM events e, organisations o

WHERE e.org_id = o.org_id

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

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'

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

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

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

SELECT booking_no, cost, quantity,

resource_code, resource_description

FROM pretty_stuff_for_users

SELECT e.description

FROM events e, organisations o

WHERE e.org_id = o.org_id

ALTER TABLE events modify (org_id not null)

SELECT booking_no, cost, quantity,

resource_code, resource_description

FROM pretty_stuff_for_users

Join Factorization

Join Factorization

If a column is not

null define it as

NOT NULL

10G – JOIN before the GROUP BY

11G – GROUP BY before the JOIN

10G – NOT IN (PROMISE_NO NULLABLE)

10G – KILLED AFTER 1 hr

11G – Rewrite as Null Aware Anti join

10G – Full Outer Join – default behaviour

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

11G Native Full Outer Join

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

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

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!!!

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

Oracle 10g – Run a whole load of random statements – all of

which require parsing

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

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

SAGE Computing Services

Customised Oracle Training Workshops and Consulting

Questions?

www.sagecomputing.com.au

penny@sagecomputing.com.au

top related