stop the chaos! get real oracle performance by query tuning part 2

44
Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2 Janis Griffin Senior DBA / Performance Evangelist

Upload: solarwinds

Post on 22-Jan-2018

267 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

Stop the Chaos! Get Real Oracle Performance by Query Tuning – Part 2Janis Griffin

Senior DBA / Performance Evangelist

Page 2: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Who am I?

• Senior DBA / Performance Evangelist for SolarWinds• [email protected]• Twitter® - @DoBoutAnything• Current – 25+ Years in Oracle®, DB2®, ASE, SQL Server®, MySQL®• DBA and Developer

• Specialize in performance Tuning• Review database performance for customers and prospects• Common question: “How do I tune it?”

Page 3: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Agenda

• A quick review of part 1• Using wait time analysis (WTA)• Reviewing the execution plan

• Understanding the optimizer• Finding the expensive steps

• Discuss several tuning techniques• SQL diagramming• Partitioning and other useful features

• How to identify coding mistakes • Engineer out the stupid

• What to do if you can’t change the code• Third-party applications• Avoiding hints

Page 4: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Who registered yesterday for SQL Tuning?

SELECT s.fname, s.lname, r.signup_dateFROM student s

INNER JOIN registration r ON s.student_id = r.student_idINNER JOIN class c ON r.class_id = c.class_id

WHERE c.name = 'SQL TUNING'AND r.signup_date BETWEEN :beg_date AND :end_dateAND r.cancelled = 'N‘

• Execution Stats – 21,829 Buffer Gets• Execution Time – 22 seconds to execute• Wait Events – Waits 90% direct path read

Case Study for Review

User

complained.

Query spent

over 3 hours in

the database.© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 5: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

Execution Plan

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 6: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

Relationship Diagram

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 7: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Recommends – three new indexes

Tuning Advisor

DECLARE

l_sql_tune_task_id VARCHAR2(100);

BEGIN

l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task ( sql_id => '&sql_id',

scope => DBMS_SQLTUNE.scope_comprehensive, time_limit => 60,

task_name => '&sql_id', description => 'Tuning task for class registration query');

DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);

END;

/

EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => '&sql_id');

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 8: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Need to know the size of the actual data sets for each step in execution plan• In Joins (Right, Left, Outer)• What are the filtering predicates?• When is each filtering predicate applied?

• Try to filter earlier rather than later

• Compare size of final result set with data read• Find the driving table

• To reduce buffer gets

Tune the Query

SELECT s.fname, s.lname, r.signup_date

FROM student s

INNER JOIN registration r ON s.student_id = r.student_id

INNER JOIN class c ON r.class_id = c.class_id

WHERE c.name = 'SQL TUNING'

AND r.signup_date BETWEEN :beg_date AND :end_date

AND r.cancelled = 'N'

Joins

Filtering

Predicates

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 9: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• “SQL Tuning” by Dan Tow• Great book that teaches SQL Diagramming• http://www.singingsql.com

SQL Diagramming

registration

student class

5

1

30

1

4%

.1%

select count(1) from registration where cancelled = 'N'

and signup_date between '2016-12-10 00:00' and '2016-12-11 00:00'

64112 / 1783066 * 100 = 3.59 or 4%

select count(1) from class where name = 'SQL TUNING'

2 / 1,267 * 100 = .1%

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 10: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

• CREATE INDEX cl_name ON class(name);

• Execution Stats – 20,348 buffer gets• Why is a full table scan still occurring on REGISTRATION?

New Execution Plan

Page 11: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• CLASS_ID not left leading in index

• Execution Stats – 20,348 buffer gets• Twice the work to use Primary Key Index on REGISTRATION

Review Index Order

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 12: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

• CREATE INDEX reg_alt ON registration(class_id);

• Execution Stats – 3000 Buffer Gets / Average Execs - .008 Secs

New Execution Plan

Page 13: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

• CREATE INDEX reg_cancel_signup ON registration(cancelled,signup_date);

Tuning Advisor Suggested Index

Execution Stats:

1107 Buffer Gets

Avg Executions:

0.140 Secs

Page 14: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

• CREATE INDEX reg_alt ON registration(class_id,signup_date, cancelled);

• Execution Stats – 445 Buffer Gets / Average Execs - .002 Secs

Better Execution Plan

Page 15: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

Performance Improved

reg_canceled_signup index

Average Wait Time per Execution for SQL Statement Class_Registration | CECE_JGRIFFIN-2

January 27, 2015

Daily Time Range: 1:00 PM-10:00 PM

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 16: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Case Study – Current Pay Check For Specific Employees

SELECT e.first_name, e.last_name, l.region_name

FROM emp e

INNER JOIN dept d ON e.department_id = d.department_id

INNER JOIN loc l ON l.location_id = d.location_id

WHERE (e.last_name LIKE :b1)

AND e.employee_id IN (

SELECT employee_id

FROM wage_pmt w

WHERE w.employee_id = e.employee_id

AND w.pay_date>= trunc(sysdate)-31);

Page 17: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Wait Time Analysis

Almost 100% on PGA

memory allocation wait. New

wait event in 12.2 – not

documented

No statistics,

Unique indexes

Added PKs and Fks

Page 18: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Execution Plan

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 19: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Understanding the Underlying Objects

Page 20: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

ACCEPT SQL_ID CHAR PROMPT 'Enter SQL_ID> 'DECLAREl_sql_tune_task_id VARCHAR2(100);

BEGINl_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task ( sql_id => '&sql_id',scope => DBMS_SQLTUNE.scope_comprehensive, time_limit => 60,task_name => '&sql_id', description => 'Tuning task for Current Paycheck');DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);

END;/EXEC DBMS_SQLTUNE.execute_tuning_task(task_name => '&sql_id');SELECT DBMS_SQLTUNE.report_tuning_task('&sql_id') AS recommendations FROM dual;EXEC DBMS_SQLTUNE.drop_tuning_task('&sql_id');

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Ask the Tuning Advisor

No recommendations

Page 21: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

SQL Diagramming

select count(1) from wage_pmt

where pay_date >= sysdate – 31

2,184 / 142,708 * 100 = 1.5%

select avg(cnt) from (select substr(last_name,1,3), count(*) cnt

from emp group by substr(last_name,1,3))

278.5 / 3,899 * 100 = .7.14% With full last nume = .1%

emp

dept

wage_pmt

975

1

37

1

.7%

2%

loc1

1

.1%

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 22: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

No change?

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Add Index on WAGE_PMT(employee_id)

Page 23: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Adjust Index on WAGE_PMT

CREATE INDEX idx_emp_dateON wage_pmt(employee_id, pay_date);

Page 24: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Improved Performance

Created index

IDX_EMP_DATE

Page 25: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• FETCH FIRST n ROWS ONLY • Retrieves first rows without scanning everything• Faster than using rownum

• OFFSET n ROWS FETCH FIRST n ROWS ONLY• Skip some number of rows

• 12.2 Approximate Query Processing• Used for approximate ‘count distinct’ values

• And adds percentile aggregation

• Allows for faster processing of large data sets• Not exact but usually within 95%+ range

• Three new parameters – alter system/session • approx_for_aggregation Default=FALSE• approx_for_count_distinct Default=FALSE• approx_for_percentile Default=NONE

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Other Tuning Tips

Page 26: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Approximate SQL Example Without Changing Code

Why is it exact?

Need to

set both

Page 27: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Convert non-partitioned table • To a partitioned table ONLINE

• Many new partition options• Automatic Lists• Multi-column Lists• Partitioned external tables• Other maintenance options

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

New 12.2 Partitioning Features

UPDATE INDEXES clause is

optional. Indexes with SYS

names will be generated if not

used.

Page 28: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Look for performance inhibitors• Cursor or row by row processing • Parallel processing

• Don’t use in an OLTP environment• Use only when accessing large data sets and additional resources can be allocated

• Nested views that use db_links• Abuse of Wild Cards (*) or No Where Clause

• Select ONLY those columns in a query which are required. • Extra columns cause more I/O on the database and increase network traffic• Code-based SQL Generators (e.g. Hibernate)

• Using functions on indexed columns (SUBSTR, TO_CHAR, UPPER, TRUNC)• Optimizer can’t use the index

• Instead move the function to the constant or variable side of equation• Consider creating a function based index

• Hard-coded hints

Engineer Out the Stupid

select… where upper(last_name) = ‘GRIFFIN’

Better way: select … where last_name = upper(:b1);

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 29: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Reduce SORT operations as they slow down your queries• Don’t use the UNION operator if you can use UNION ALL• Avoid the DISTINCT keyword if you don’t need it

• Ensure the left-leading column of a multi-column index is reference• Otherwise an INDEX SKIP SCAN may occur

• Often no better than a FULL TABLE SCAN

• Try to avoid Cartesian product queries• Use bind variables instead of literal values

• Reduces repeated parsing of the same statement

• If using sub-queries, make use of the EXISTS operator when possible• Optimizer will stop with a match and avoid a FULL TABLE SCAN

• Try to use an index if less than 5% of the data needs to be accessed• Exception: small table are best accessed through a FULL TABLE SCAN

• Consider keeping in memory

More Do’s and Don’ts

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 30: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Use equi-joins whenever possible• Try not to use ‘not in’, !=, <>, not null, etc.• Optimizer has more choices to choose from

• Avoid complex expressions such as NVL(col1,0), TO_DATE(), TO_NUMBER()• They prevent the optimizer from assigning valid cardinality or selectivity estimates • Can affect the overall plan and the join methods

• Avoid joining complex views• May instantiate all views to run query against (reading too much data)• Querying views requires all tables from the view to be accessed

• If they aren’t required, then don’t use the view

• Use the partition key in the ‘WHERE’ clause if querying a partitioned table • Partition pruning will be used to reduce the amount of data read

Avoid Common Pitfalls

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 31: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• If you can hint it, baseline it (per Tom Kyte)• Alternative to using hints

• Hints difficult to manage over time• Once added, usually forgotten about

• Third-party software – can’t modify code• Example:Merge Join Cartesian > Nested Loop

select /* jg */ p.product_name

from order_items o, product p

where o.unit_price = :b1

and o.quantity > :b2

and o.product_id = p.product_id

and p.product_id = :b3;

What to Do If You Can't Change the Query

select /*+ USE_NL(o p) */ /* jg */ p.product_name

from order_items o, product p

where o.unit_price = :b1

and o.quantity > :b2

and o.product_id = p.product_id

and p.product_id = :b3;

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 32: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Create baseline of original planAlter session set optimizer_capture_sql_plan_baselines = TRUE;• Or dbms_spm.load_plans_from_cursor_cache

• Example next slide

How to Change the Baseline

From cache Baseline

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 33: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Manually run hinted query• Hint = /*+ USE_NL(p) +/

Change the Baseline – Cont.

Get SQL_ID, Plan hash value from cache Load from cache into baseline

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 34: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

SELECT c_last, c_first, c_street_1, c_city, c_state, c_zip,c_phone, o_entry_d, d_name, ol_delivery_d, ol_quantity, ol_amount

FROM order_line, orders, district, customer, stockWHERE o_id = ol_o_idAND o_c_id=c_idAND s_i_id = ol_i_idAND d_id = ol_d_idAND ol_w_id = :B2AND ol_d_id = :B4AND (ol_o_id < :B3 )AND ol_o_id >= (:B3 - 20)AND s_w_id = :B2AND s_quantity < :B1AND d_id = :B4AND c_last like :B5 ;

Another Case Study – Orders by Customer Last Name

Page 35: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Review the Execution Plan

select * from table (dbms_xplan.display_cursor(null,null, format=> '+report'));

Page 36: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

• Stock:

Get Object Information

create index stock_idx

on stock

(s_i_id, s_w_id, s_quantity);

Page 37: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

• Orders:

Get Object Information

Actual Rows = 60,000

Page 38: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

Find the Driving Table

orders

stock

district

100

130

1

.7%

.03

select count(*) from order_line

where ol_o_id < 200 and ol_o_id >= 200-20;

3941 / 600916 * 100 = .6558%

select avg(cnt) from (select c_last, count(*) cnt

from customer group by c_last);

20 / 60000 * 100 = .03333%

Filter on Stock: 3109 / 283000 * 100 = 1%

order_line

customerwarehouse

WHERE o_id = ol_o_id

AND o_c_id=c_id

AND s_i_id = ol_i_id

AND d_id = ol_d_id

AND ol_w_id = :B2

AND ol_d_id = :B4

AND (ol_o_id < :B3 )

AND ol_o_id >= (:B3 - 20)

AND s_w_id = :B2

AND s_quantity < :B1

AND d_id = :B4

AND c_last like :B5 ;

1

20

1

1

660092

10

1%

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 39: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• create index stock_idx on stock (s_i_id, s_w_id, s_quantity);

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Engineer Out the Stupid

Page 40: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• create index orders_i2 on orders(o_id,o_c_id, o_entry_d);

Add Index on Orders to INCLUDE Customer

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Page 41: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Did Performance Improve?

Added Index on

Stock

Added Index on

Orders

Page 42: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Make sure you are tuning the correct query• Use wait time analysis

• Understand the execution plan • Focus on the costly steps• Know what the optimizer knows

• Try these tuning techniques • SQL diagraming to find the best execution plan• Consider new fetch, approximate and partitioning features

• Engineer out the stupid• Be on the lookout for coding mistakes

• If you can’t change the code• Try using baselines or patches

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Summary

Page 43: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

• Try Database Performance Analyzer FREE for 14 days• Improve root cause of slow performance

• Quickly identify root cause of issues that impact end-user response time• See historical trends over days, months, and years• Understand impact of VMware® performance • Agentless architecture with no dependence on Oracle Packs, installs in minutes

© 2017 SolarWinds Worldwide, LLC. All rights reserved.

Resolve performance issues quickly - free trial

www.solarwinds.com/dpa-download/

Page 44: Stop the Chaos! Get Real Oracle Performance by Query Tuning Part 2

The SolarWinds, SolarWinds & Design, Orion, and THWACK trademarks are the exclusive

property of SolarWinds Worldwide, LLC or its affiliates, are registered with the U.S.

Patent and Trademark Office, and may be registered or pending registration in other

countries. All other SolarWinds trademarks, service marks, and logos may be common

law marks or are registered or pending registration. All other trademarks mentioned

herein are used for identification purposes only and are trademarks of (and may be

registered trademarks) of their respective companies.

Thank You!!!