2026-03-12 20:23:15
This commit is contained in:
111
tpt/ast/02_choosing_join_order.sql
Normal file
111
tpt/ast/02_choosing_join_order.sql
Normal file
@@ -0,0 +1,111 @@
|
||||
-- Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
-- Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
--
|
||||
-- File name: 02_choosing_join_order.sql
|
||||
--
|
||||
-- Purpose: Advanced Oracle SQL Tuning demo script
|
||||
-- Author: Tanel Poder
|
||||
-- Copyright: (c) http://www.tanelpoder.com
|
||||
--
|
||||
-- Usage: You can run the query against Oracle's sample schemas (SH)
|
||||
-- The optimizer stats have to be updated to cause trouble.
|
||||
-- See the commented out code below
|
||||
--
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- in Oracle 11gR2, set the cardinality feedback option to false for demo stability purposes
|
||||
-- alter session set "_optimizer_use_feedback"=false;
|
||||
--
|
||||
-- Set statistics_level = all for measuring optimizer misestimate (or use V$SQL_MONITOR):
|
||||
-- alter session set statistics_level = all;
|
||||
--
|
||||
-- Cause trouble for the optimizer:
|
||||
-- EXEC DBMS_STATS.SET_TABLE_STATS('SH','CUSTOMERS', NUMROWS=>1, NUMBLKS=>1, NO_INVALIDATE=>FALSE);
|
||||
|
||||
SELECT /*+ MONITOR */
|
||||
ch.channel_desc
|
||||
, co.country_iso_code co
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
, sum(s.quantity_sold)
|
||||
, sum(s.amount_sold)
|
||||
FROM
|
||||
sh.sales s
|
||||
, sh.customers cu
|
||||
, sh.countries co
|
||||
, sh.products p
|
||||
, sh.channels ch
|
||||
WHERE
|
||||
-- join
|
||||
s.cust_id = cu.cust_id
|
||||
AND cu.country_id = co.country_id
|
||||
AND s.prod_id = p.prod_id
|
||||
AND s.channel_id = ch.channel_id
|
||||
-- filter
|
||||
AND ch.channel_class = 'Direct'
|
||||
AND co.country_iso_code = 'US'
|
||||
AND p.prod_category = 'Electronics'
|
||||
GROUP BY
|
||||
ch.channel_desc
|
||||
, co.country_iso_code
|
||||
, cu.cust_city
|
||||
, p.prod_category
|
||||
/
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- SQL Profiles (require Tuning + Diag Pack):
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- VAR sql_fulltext CLOB
|
||||
-- EXEC SELECT sql_fulltext INTO :sql_fulltext FROM v$sql WHERE sql_id = '1ka5g0kh4h6pc' AND rownum = 1;
|
||||
--
|
||||
-- Example 1: Set Join order:
|
||||
-- EXEC DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=>sys.sqlprof_attr('LEADING(@"SEL$1" "CO"@"SEL$1" "CH"@"SEL$1" "CU"@"SEL$1" "S"@"SEL$1" "P"@"SEL$1")'), name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
--
|
||||
-- Example 2: Adjust cardinality:
|
||||
-- EXEC DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=>sys.sqlprof_attr('CARDINALITY(@"SEL$1" "CU"@"SEL$1" 100000)'), name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
--
|
||||
-- Example 3: Set multiple hints:
|
||||
-- DECLARE
|
||||
-- hints sys.sqlprof_attr := sys.sqlprof_attr(
|
||||
-- ('LEADING(@"SEL$1" "CO"@"SEL$1" "CH"@"SEL$1"')
|
||||
-- , ('CARDINALITY(@"SEL$1" "CU"@"SEL$1" 100000)')
|
||||
-- );
|
||||
-- BEGIN
|
||||
-- DBMS_SQLTUNE.IMPORT_SQL_PROFILE(sql_text=>:sql_fulltext, profile=> hints, name=> 'MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
-- END;
|
||||
-- /
|
||||
--
|
||||
-- Drop the profile:
|
||||
-- EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('MANUAL_PROFILE_1ka5g0kh4h6pc');
|
||||
--
|
||||
--
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- SQL Plan Baselines - DBMS_SPM in EE licenses - see http://jonathanlewis.wordpress.com/2011/01/12/fake-baselines/
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
-- bad_sqlid = 1ka5g0kh4h6pc
|
||||
-- good_sqlid = 1fzf3vqv0f49q
|
||||
|
||||
-- 1) Manually run the query with hints, params, etc to get the plan you want (the good query)
|
||||
--
|
||||
-- 2) Create a disabled plan baseline for the "bad query":
|
||||
-- VAR x NUMBER
|
||||
-- EXEC :x:= DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE('&bad_sqlid', enabled=>'NO');
|
||||
--
|
||||
-- 3) SELECT sql_handle FROM dba_sql_plan_baselines WHERE sql_text = '<your sql_text>';
|
||||
--
|
||||
-- 4) Associate the "good query" plan with the "bad query" SQL plan baseline:
|
||||
-- DEF good_sql_id = 1fzf3vqv0f49q
|
||||
-- DEF good_plan_hash_value = 2863714589
|
||||
-- DEF sql_handle_for_original = SQL_4b3ef772af37954d
|
||||
|
||||
-- VAR x NUMBER
|
||||
--
|
||||
-- exec :x := dbms_spm.load_plans_from_cursor_cache( -
|
||||
-- sql_id => '&good_sql_id', -
|
||||
-- plan_hash_value => &good_plan_hash_value, -
|
||||
-- sql_handle => '&sql_handle_for_original');
|
||||
--
|
||||
Reference in New Issue
Block a user