webinar
DESCRIPTION
Webinar discriptionTRANSCRIPT
Making Impac,ul Performance Changes
Karen Morton Sr. Technical Consultant
1
An Embarcadero Oracle Community Webinar
3
July 31 Diagnosing SQL Performance Problems
August 29
Making SQL Performance SoluIons “SIck”
September 26 Making Impac,ul Performance Changes
Topics
• Common ways to rewrite SQL to make it perform beNer and more consistently
• How and when to index – AddiIons or modificaIons to provide best soluIon
• About SQL Tuning Advisor – When it helps – When it doesn't
4
5
Rewriting
SQL
First things first
(This stuff is really important)
Review the statement.
What is it supposed to do?
Tune the quesIon, not the query. – Tom Kyte
Collect data.
Review staIsIcs.
indexes and
constraints.
Check
Execute the query.
Evaluate the plan.
(compare esImates to actuals)
Where are the big hiNers?
Refactor the statement.
(if you should)
Modify or Add indexes, constraints, staIsIcs.
(if you should)
T T D (Test To DestrucIon)
Iterate unIl target met or no
further improvement possible
Things To Keep In Mind
How do you do simple, yet effecIve, tesIng?
Name your SQL SELECT /* kmtest */ … FROM tab …
/*+ gather_plan_staIsIcs */ (staIsIcs_level = ALL)
dbms_xplan.display_cursor ('ALLSTATS LAST')
SELECT xplan.*!FROM !(!select max(sql_id) keep! (dense_rank last order by last_active_time) sql_id! , max(child_number) keep! (dense_rank last order by last_active_time) child_number! from v$sql! where upper(sql_text) like '%&1%'! and upper(sql_text) not like !
! !'%FROM V$SQL WHERE UPPER(SQL_TEXT) LIKE %'!) sqlinfo,!table(DBMS_XPLAN.DISPLAY_CURSOR!(sqlinfo.sql_id, sqlinfo.child_number, 'ALLSTATS LAST')) xplan ;!!!
-- +COST +BYTES +PEEKED_BINDS!
/*+ monitor */
dbms_sqltune.report_sql_monitor (TEXT, HTML, XML, ACTIVE)
SELECT dbms_sqltune.report_sql_monitor!(!! !SQL_ID => '&sql_id', !! !SESSION_ID => '&session_id',!! !SESSION_SERIAL => '&session_serial',!! !TYPE => '&report_format'!
) !FROM dual ;!
Monitored statements can be found in V$SQL_MONITOR
Know thy data. (and thy schema)
Visualize (Visual SQL Tuning)
output from Embarcadero DB OpImizer
33
How do you know when rewriIng SQL is the
best opIon?
Look for "column-‐less" joined tables.
SELECT b.* FROM a, b WHERE a.col1 = b.col1 AND b.col2 = <condition>
SELECT b.* FROM b WHERE b.col2 = <condition> AND EXISTS (SELECT null FROM a WHERE a.col1 = b.col1)
This
Becomes
Look for improper outer joins.
AND tab1.col1 = tab2.col1 (+) AND tab2.col2 = <condition>
AND tab1.col1 = tab2.col1 AND tab2.col2 = <condition>
This
Becomes
Because the condiIon would be null for the outer joined row, so the predicate could never be true.
Look for repeated use of same tables and predicates.
SELECT rite.event_name, count(*) FROM riffs.rf_order ro, riffs.rf_order_item roi, riffs.rf_item_transaction rit,
riffs.rf_item_transaction_event rite WHERE ro.is_test = '0' AND ro.order_id = roi.order_id AND roi.order_item_id = rit.order_item_id AND roi.order_id = rit.order_id AND rit.transaction_id = rite.transaction_id AND (rite.event_name >'AUTHORIZED' OR rite.event_name <'AUTHORIZED') GROUP BY rite.event_name UNION ALL SELECT 'TRANSACTION_INITIATED', count(*) FROM (SELECT count(*) FROM riffs.rf_order ro, riffs.rf_order_item roi,
riffs.rf_item_transaction rit, riffs.rf_item_transaction_event rite
WHERE ro.is_test = '0' AND ro.order_id = roi.order_id AND roi.order_item_id = rit.order_item_id AND roi.order_id = rit.order_id AND rit.transaction_id = rite.transaction_id AND rite.event_name = 'AUTHORIZED' GROUP BY substr(rit.TRANSACTION_ID,1,INSTR(rit.TRANSACTION_ID,'_')-1))
Look for simple predicates ORed with other
predicates in ranges.
AND col1 > <condition> OR col2 > <condition>
AND col1 > <condition> UNION / UNION ALL AND col2 > <condition>
This
Becomes
Because a row could not be rejected when one predicate is false without checking the other predicates.
Look for DISTINCT/UNION
to remove duplicates.
Consider using IN or EXISTS instead.
Check viability of indexes.
Do indexes provide proper coverage?
44
How and When
to Index
45
For many years, inadequate indexing has been the most common cause of performance disappointments.
– Tapio Lahdenmäki
Indexing Problems
• Indexes that do not have sufficient columns to support all predicates
• Not enough indexes present – Numerous single-‐column but few mulI-‐column
• Indexes with the right columns but in the wrong order
46
47
How many is "too" many?
48
Heavy DML? Large, bulk loads?
or Mostly query?
49
Indexes support query performance
50
SELECT !cust_id, cust_first_name!FROM! ! !customers!WHERE ! !cust_last_name = 'Ruddy'!AND! ! !cust_city = 'Ede'!ORDER BY cust_first_name ;!
Index present on CUST_LAST_NAME, CUST_FIRST_NAME # rows in table = 55,500
Inadequate Index
51
Note the number of rows that are thrown away in step 1 (79).
52
Index on CUST_LAST_NAME, CUST_CITY No throwaway
Index on CUST_CITY, CUST_LAST_NAME, CUST_FIRST_NAME, CUST_ID No throwaway, no sort
Index Strategies
All columns from equality predicates Add columns used in ORDER BY Add all remaining columns from column list
53
A 3 star index is owen called a "fat" index. Range predicates are typically placed awer 1 and 2 star columns.
54
The key to determining an ideal index
The index should provide adequate enough screening to minimize table accesses.
55
SQL Tuning
Advisor
What STA Can Recommend
• CollecIon of staIsIcs – Objects with stale or missing staIsIcs are idenIfied and appropriate recommendaIons are made to remedy the problem
• CreaIon of new indexes – Indexes that can "significantly" enhance performance
56
What STA Can Recommend
• Restructuring of the SQL statement • CreaIon of a SQL profile – Remedy execuIon plan inefficiencies with a SQL profile
57
Great for poinIng out the "obvious".
Finds the low-‐hanging fruit.
59
Finding: An expensive cartesian product operaIon was found at line ID 2 of the execuIon plan. RecommendaIons: Consider removing the disconnected table or view from this statement or add a join condiIon which refers to it. RaIonale: A cartesian product should be avoided whenever possible because it is an expensive operaIon and might produce a large amount of data.
SQL Restructuring Example 1
60
Finding: The opImizer could not unnest the subquery at line ID 1 of the execuIon plan. RecommendaIons: 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.
SQL Restructuring Example 2
61
RaIonale: A "FILTER" operaIon can be very expensive because it evaluates the subquery for each row in the parent query. The subquery, when unnested can drasIcally improve the execuIon Ime because the "FILTER" operaIon is converted into a join. Be aware that "NOT IN" and "NOT EXISTS" might produce different results for "NULL" values.
SQL Restructuring Example 2
SQL Profiles use OPT_ESTIMATE
hints.
"Fudge factors"
Not a subsItute for human intelligence.
Monkey vs. Astronaut
Recap
• Look for common anI-‐paNerns in SQL • Gather enough diagnosIc data to know where the problem originates
• Learn what the opImizer expects (and give it what it wants!)
• Think about your indexing strategy • Design indexes for opImal coverage • Use STA as a pointer to problems, not necessarily as the soluIon
64
Q & A
65
Thank you!