Oracle Database 10g SQL Optimization
Oracle Database 10g SQL Optimization
Jonathan Lewis
Agenda
Who am I Areas of optimisation Past, Present and Future Q and A
Most slides have a foot-note. This is a brief summary of the comments that I should have made whilst displaying the slide, and is there for later reference.
Oracle 10 Evolution 2
Who am I ?
Independent Consultant. 19+ years in IT 16+ using Oracle Strategy, Design, Review Briefings, Seminars Trouble-shooting www.jlcomp.demon.co.uk
Jonathan Lewis 2003-2004 Oracle 10 Evolution 3
What is "Optimisation" ?
What do we want ?
Better performance for less cash
Better tools
let the dba/developer do a better job, faster
When you think of optimisation, it's not just about ways to rewrite the SQL to make it go faster - Oracle keeps inventing new strategies, and new tools.
Oracle 10 Evolution 4
As an indication of how things keep changing - and how we have to keep reviewing code on upgrades - we look at subquery unnesting.
Oracle 10 Evolution 5
If you did not include the hint (which is not needed in Oracle 9) a query like this could be slow and expensive in Oracle 8.
Oracle 10 Evolution 6
The execution plan suggests (incorrectly) that Oracle is doing a full tablescan and sort of the subqueried emp table for each row of the driving emp table.
Oracle 10 Evolution 7
dept_no, avg(sal) av_sal from emp group by dept_no ) inner, emp outer where outer.dept_no = inner.dept_no and outer.sal > inner.av_sal;
But the introduction of in-line views gave you an option for rewriting it to go faster (most of the time). See Gaja Vaidyanatha Performance Tuning 101.
Oracle 10 Evolution 8
SELECT STATEMENT Optimizer=CHOOSE (Cost=121 Card=1000) HASH JOIN (Cost=121 Card=1000) VIEW (Cost=86 Card=6) SORT (GROUP BY) (Cost=86 Card=6) TABLE ACCESS (FULL) OF EMP (Cost=34 Card=20000) TABLE ACCESS (FULL) OF EMP (Cost=34 Card=20000)
The plan shows that we have explicitly created a 'holding' view of the data, and then done a hash join from this temporary set to the main table.
Oracle 10 Evolution 9
Oracle 10 Evolution 10
Unnesting subqueries is often the best thing to do, but it isn't always the best thing to do. Oracle 10g checks to see if it is a good idea - Oracle 9i may not.
Oracle 10 Evolution 11
You may do better than unnesting anyway. When you unnest you still scan the emp table twice. If you switch to analytic functions, you scan it once.
Oracle 10 Evolution 12
-- (2.8GHz)
-- PX choke -- PX choke
One of the major features of Oracle 9 that should be included as part of the standard migration is the CPU-based costing feature. It is mandatory in 10g
Oracle 10 Evolution 13
This formula for cost appears in the 9.2 manuals. Effectively it says that cost really is supposed to be a prediction of elapsed time.
Oracle 10 Evolution 14
There are a few little traps to costing - whether you use the traditional or new method - Changing the block size for a table will change the cost of scanning
Oracle 10 Evolution 15
Search_columns:
Access_predicates (index): (T1.ID1 = 14 AND T1.ID3 >= 1 AND T1.ID3 <= 20)
Always check for new columns in the plan_table, (utlxplan.sql, catplan.sql). How much of the index goes into the start-key, stop-key calculations.
Oracle 10 Evolution 17
Filter_predicates (index): (T1.ID3 >= 1 AND T1.ID3 <= 20) Filter_predicates (table): (T1.N1=TO_NUMBER('a') AND TO_NUMBER(T1.V1)>15)
What predicates have to be checked on every single entry from the leaf entry, and table entry. Implicit conversions suddenly become explicit and visible
Oracle 10 Evolution 18
The unhelpful filter line of the old Oracle 8 plan would become much more meaningful using the new columns in Oracle 9's explain plan
Oracle 10 Evolution 19
Not only do you have a better plan_table, you also have real-time excution plans made visible in Oracle 9i - with the actual run-time statistics.
Oracle 10 Evolution 20
10
If we look at the correlated subquery again, we see that the execution plan is not telling us everything - the statistics (starts in particular) are very helpful.
Oracle 10 Evolution 21
Elapsed times include waiting on following events: Event waited on Times Max Wait Tot Waited ----------------------------- Waited -------- ---------SQL*Net message to client 111 0.00 0.00 SQL*Net message from client 110 83.97 103.47 SQL*Net more data from client 16 0.05 0.13 SQL*Net more data to client 48 0.02 0.05 SQL*Net message to dblink 11 0.00 0.00 SQL*Net message from dblink 11 0.02 0.02 log file sync 3 0.00 0.00
Oracle 9i also allows you to summarise wait states in a trace file . Generated from a 10046 level 8 trace, or using the improved (legal) sql_trace facility.
Oracle 10 Evolution 22
11
10
Oracle 10 is very different from it predecessors because a huge fraction of the change is about optimising your use of time - not the machine's.
Oracle 10 Evolution 23
Execution plan from 9i TABLE ACCESS TEST_USER T1 (by index rowid) Filter (T1.N3+1 = 1 OR T1.N3+1 = 2 OR T1.N3+1 = 3) INDEX NON-UNIQUE TEST_USER I1 (range scan) (Columns 3) Access (T1.N1 = 1 AND T1.N2 = 1 AND T1.N4 = 1) Filter (T1.N4 = 1)
The optimiser is always being enhanced to improve the efficiency at all sort of levels. In 9.2, column n3 is checked only after you get to the table.
Oracle 10 Evolution 24
12
Execution plan from 10g TABLE ACCESS (analyzed) TABLE TEST_USER T1 (by index rowid) INDEX (analyzed) INDEX TEST_USER I1 (range scan)(Columns 3) Access (N1 = 1 AND N2 = 1 AND N4 = 1) Filter (N4 = 1 AND (N3+1 = 1 OR N3+1 = 2 OR N3+1 = 3))
On the upgrade to 10g, a query like this might suddenly show a performance improvement because the check of column n3 can now be done in the index.
Oracle 10 Evolution 25
Of course, there are inevitably some improvements from coding in new optimisation techniques and execution paths - for example outer hash joins
Oracle 10 Evolution 26
13
Oracle has invented, and the ANSI committee has approved, the partiitoned outer join. (Only for use with ANSI outer join syntax, though)
Oracle 10 Evolution 27
EVENT_ID Buffer Buffer Buffer Buffer Enqueue Enqueue Enqueue Enqueue Wait Wait Wait Wait
CHK_PT 1 2 3 4 1 2 3 4 1 2 3 4
SCORE 8
3 10
CHK_PT 1 4 1 4 2 4
SCORE 8 3 10 15 12 17
15
12 17
Oracle 10 Evolution 28
How can you get from the output on the left to the output on the right ? A simple outer join will not do - we need an 'outer join per event id'.
14
Better hints
index (t1, index (t1 i1) v9.2 t1(col1, col2))v10.1 v10.1 v10.1 v9.2 v10.1
no_index_ss (t3) no_index_ffs (t3 i1 i2 i3) leading (t3) leading (t3 t4 t1 t5 t2) The strangest hint in 10g /*+ IGNORE_OPTIM_EMBEDDED_HINTS
Jonathan Lewis 2003-2004
*/
Some of the enhancements are very low key, and yet extremely effective. For example, index hints just got safer, and the leading hint is now really useful.
Oracle 10 Evolution 29
Under 8i and 9i, the coalesce could only produce a single block from a set of adjacent blocks - so missed many opportunities for improving the index.
Oracle 10 Evolution 30
15
Index coalesce - 10
alter index i1 coalesce;
Oracle 10 can take a longer stream of index leaf blocks, and distribute the discovered rows more widely. (The branch block restriction still applies)
Oracle 10 Evolution 31
dbms_stats enhancements
procedure alter_stats_history_retention procedure get_stats_history_retention procedure restore_table_stats procedure purge_stats procedure gather_fixed_objects_stats procedure gather_dictionary_stats procedure lock_table_stats procedure unlock_table_stats
There are plenty of enhancements to investigate in dbms_stats - including analysing the X$ objects, locking statistics, and recalling historical stats.
Oracle 10 Evolution 32
16
Some information that gets dumped to disc (by mmon) is an extract from v$segstat. This is one of the two ways in which the data is recorded.
Oracle 10 Evolution 33
Cache history is not currently used - but there are parameters waiting to be set to enable it.
Jonathan Lewis 2003-2004
And one reason the v$segstat data is recorded becomes apparent when you discover the ind_stat$ and tab_stat$ tables, which hold 'local' cache hit ratios
Oracle 10 Evolution 34
17
How much DID you know about join order effects ? _optimizer_join_order_control = 3
There are 46 parameters that change their values if you change the setting for optimizer_features_enabled from 8.1.7.4, through 9.2.0.4 to 10.1.0.2
Oracle 10 Evolution 35
For all those over-zealous developers who like to include the username and time in every single procedure - the cost of hitting dual has dropped.
Oracle 10 Evolution 36
18
Oracle 10g will take an inefficient pl/sql loop like the above 'traditional' form, and operate as if it were written in the 'array processing form'.
Oracle 10 Evolution 37
Using "execute immediate' to build strings in a pl/sql function is a popular method. The SQL doesn't get into the pl/sql cursor cache - until verion 10g.
19
-- 4 indexes
10.1.0.2 0 0 0 0 ..
Oracle 10 Evolution 39
partition p199 values less than (199) ); alter table t1 drop partition p001; update tabpart$ set part# = :1 where obj# = :2 and bo# = :3
call Parse Execute Fetch total count 198 198 0 396 cpu 0.01 0.10 0.00 0.11 elapsed 0.01 0.06 0.00 0.08 disk 0 0 0 0 query 0 199 0 199 current 0 202 0 202 rows 0 198 0 198
If you've ever dropped a partition from a partitioned table with a very large number of partitions, you may have noticed it takes some time. Trace it.
Oracle 10 Evolution 40
20
Results 10.1.0.2
OBJ# 54815 54818 54820 54822 54824 PART# 10 20 30 40 50
select -- view tabpartv$ obj#, dataobj#, bo#, row_number() over (partition by bo# order by part#), etc from tabpart$
Jonathan Lewis 2003-2004
10g does it better; and when you check the data dictionary content, and the view definitions for the two versions, you find out why.
Oracle 10 Evolution 41
Tuning Advisor
select /*+ example 1 */ padding from t1 where n1 = 15; select /*+ example 2 */ {list of columns} from t1, t2 where t2.n2 = 15 and t2.n1 = 15 and t1.n2 = t2.n2 and t1.n1 = t2.n1 ; select /*+ example 3 */ n2 from t1 where n1 not in (select n1 from t2) ;
Possibly the most significant benefit of 10g is the tool that allows you to ask Oracle to find better optimisation paths for your SQL - like these examples.
Oracle 10 Evolution 42
21
22
23
Apart from suggesting that an index would be appropriate, and giving an indication of the benefit, you can ask to see the resulting execution plan
Oracle 10 Evolution 48
24
Most importantly, each recommendation comes with a Rationale. The bit I particularly like is the reminder to test with a representative workload.
Oracle 10 Evolution 49
25
26
Oracle 10 Evolution 54
27
from
dbms_sqltune.drop_sql_profile('SYS_SQLPROF_040624083819387');
If you accept a profile, you can see it in the view dba_sql_profiles. You cannot see what it is doing, though. But you can gets its identify to drop it.
Oracle 10 Evolution 55
Oracle 10 Evolution 56
28
Recommendations Consider replacing "NOT IN" with "NOT EXISTS" or ensure that columns used on both sides of the "NOT IN" operator are declared "NOT NULL" by adding either "NOT NULL" constraints or "IS NOT NULL" predicates.
In this case, the optimizer cannot do an internal rewrite and guarantee the results - but tells me that if I enforce some constraints, a rewrite is possible.
Oracle 10 Evolution 58
29
In this case, the rationale even goes so far as to teach you something about how SQL works. The warning is one that some 'gurus' don't seem to know.
Oracle 10 Evolution 59
Conclusion
New features can improve application performance New kernel code improves the database performance New tools improve your performance
Oracle 10 Evolution 60
30