--- how to find SQL plan changes
select to_char(min(s.end_interval_time),
'YYYY-MM-DD HH24:MI'
) sample_end
--, s.snap_id
, q.sql_id
, q.plan_hash_value
, q.instance_number inst_id
, sum(q.EXECUTIONS_DELTA) execs9
, round((sum(ELAPSED_TIME_delta)/greatest(sum(executions_delta),
1
)/
1000
/
1000
),
3
) ela_sec
, round((sum(CPU_TIME_delta)/greatest(sum(executions_delta),
1
)/
1000
/
1000
),
3
) cpu_sec
, round((sum(rows_processed_delta)/greatest(sum(executions_delta),
1
)),
1
) avg_rows
, round((sum(fetches_delta)/greatest(sum(executions_delta),
1
)),
1
) avg_fetches
, round(sum(BUFFER_GETS_delta)/greatest(sum(executions_delta),
1
)) lio_per_exec
, round(sum(DISK_READS_delta)/greatest(sum(executions_delta),
1
)) pio_per_exec
, round((sum(iowait_delta)/greatest(sum(executions_delta),
1
)/
1000
/
1000
),
1
) iowait_sec
-- , round((sum(clwait_delta)/greatest(sum(executions_delta),
1
)/
1000
),
1
) clwait_sec
-- , round((sum(apwait_delta)/greatest(sum(executions_delta),
1
)/
1000
),
1
) apwait_sec
-- , round((sum(ccwait_delta)/greatest(sum(executions_delta),
1
)/
1000
),
1
) ccnwait_sec
from dba_hist_sqlstat q, dba_hist_snapshot s
where q.SQL_ID=trim(
'&1'
)
and s.snap_id = q.snap_id
and s.dbid = q.dbid
and s.instance_number = q.instance_number
and s.end_interval_time between ( sysdate - &
2
) and ( sysdate - &
2
+ &
3
)
group by s.snap_id, q.sql_id, q.plan_hash_value, q.instance_number
order by s.snap_id, q.sql_id, q.plan_hash_value, q.instance_number
-- if you find a bad plan then try purging it
select inst_id,plan_hash_value,
'exec sys.DBMS_SHARED_POOL.PURGE ('
''
||ADDRESS||
', '
||HASH_VALUE||
''
', '
'C'
');'
from gV$SQL where sql_id in (
'1pfb281d5f37c'
) order by plan_hash_value;
-- To check stats and collect stats if stale
SELECT a.object_owner,
a.object_name,
a.object_type,
b.stale_stats
FROM v$sql_plan a
JOIN dba_tab_statistics b
ON a.object_owner = b.owner AND a.object_name = b.TABLE_NAME
WHERE b.object_type =
'TABLE'
AND a.sql_id = TRIM (
'&1'
)
AND (stale_stats IS NULL OR stale_stats =
'YES'
)
UNION ALL
SELECT a.object_owner,
a.object_name,
a.object_type,
b.stale_stats
FROM v$sql_plan a
JOIN dba_tab_statistics b
ON a.object_owner = b.owner AND a.object_name = b.PARTITION_NAME
WHERE b.object_type =
'PARTITION'
AND a.sql_id = TRIM (
'&1'
)
AND (stale_stats IS NULL OR stale_stats =
'YES'
)
UNION ALL
SELECT a.object_owner,
a.object_name,
b.object_type,
b.stale_stats
FROM v$sql_plan a
JOIN dba_ind_statistics b
ON a.object_owner = b.owner AND a.object_name = b.index_name
WHERE b.object_type!=
'SUBPARTITION'
and a.sql_id = TRIM (
'&1'
)
AND (stale_stats IS NULL OR stale_stats =
'YES'
);
-- if you decide to create a SQL baseline after all analysis
SELECT * FROM table(DBMS_XPLAN.DISPLAY_AWR(
'17n0jry7qhtdx'
));
-- look up AWR history to find SQL detailed statistics. Pick up the snapshots in which the SQL has had a good or better plan.
/* Formatted on 1/23/2018 10:06:30 AM (QP5 v5.300) */
SELECT ss.snap_id,
ss.instance_number,
sn.end_interval_time,
ss.plan_hash_value,
ss.elapsed_time_delta /
1000
/
1000
/ ss.executions_delta
avg_time_per_run,
elapsed_time_total /
1000
/
1000
total_elapsed_time,
ss.executions_delta exe_times,
ss.fetches_delta,
ss.rows_processed_delta processed_rows,
iowait_delta / ss.executions_delta per_IO_wait,
ss.cpu_time_delta / ss.executions_delta Per_CPU_time,
disk_reads_delta / ss.executions_delta Per_disk_R,
buffer_gets_delta / ss.executions_delta Per_buffer_R
FROM dba_hist_sqlstat ss, dba_hist_snapshot sn
WHERE ss.snap_id = sn.snap_id
AND ss.instance_number = sn.instance_number
AND ss.sql_id =
'&sql_id'
AND ss.executions_delta >
0
ORDER BY ss.snap_id DESC,
1
;
-- snap_id=
121097
-- create a sql tuning set. You can name it to whatever that is easy to find its purpose.
set serveroutput on
exec dbms_sqltune.create_sqlset(sqlset_name =>
'&SQL_set_name'
,description =>
'&SQL_set_name'
);
-- load SQLs that you want to tune in the above created SQL tuning set. Enter the snapshot ID in which the target sql had a good plan. Enter the ID of the SQL.
set serveroutput on
declare
baseline_ref_cur DBMS_SQLTUNE.SQLSET_CURSOR;
begin
open baseline_ref_cur
for
select VALUE(p) from table(
DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY(&snapshot_start, &snapshot_end,
'sql_id='
||CHR(
39
)||
'&sql_id'
||CHR(
39
)||
''
,NULL,NULL,NULL,NULL,NULL,NULL,
'ALL'
)) p;
DBMS_SQLTUNE.LOAD_SQLSET(
'&SQL_set_name'
, baseline_ref_cur);
end;
/
declare
my_int pls_integer;
begin
my_int := dbms_spm.load_plans_from_sqlset (
sqlset_name =>
'&SQL_set_name'
,
basic_filter =>
'sql_id='
'&sql_id'
''
,
sqlset_owner =>
'AIUDKC3'
,
fixed =>
'NO'
,
enabled =>
'YES'
);
DBMS_OUTPUT.PUT_line(my_int);
end;
/
select * from dba_sql_plan_baselines order by created desc;
-- Below is mostly not needed but if you came to a conclusion and looking to copy SQL profile from one env. to other env.
-- Run it in theta from where you want to export sql profile
EXEC DBMS_SQLTUNE.CREATE_STGTAB_SQLPROF (table_name =>
'PROFILE_STGTAB_86dxp1c32fd42'
);
EXEC DBMS_SQLTUNE.PACK_STGTAB_SQLPROF (profile_name =>
'SYS_SQLPROF_036f7c7ee4560000'
, staging_table_name =>
'PROFILE_STGTAB_86dxp1c32fd42'
);
select * from PROFILE_STGTAB;
-- export and improt above table
expdp tables=PROFILE_STGTAB_86dxp1c32fd42 dumpfile=PROFILE_STGTAB_86dxp1c32fd42.dmp directory=scripts;
impdp tables=PROFILE_STGTAB_86dxp1c32fd42 dumpfile=PROFILE_STGTAB_86dxp1c32fd42.dmp directory=conv_dir;
-- ON target database
EXEC DBMS_SQLTUNE.CREATE_STGTAB_SQLPROF (table_name =>
'PROFILE_STGTAB'
);
select * from PROFILE_STGTAB; -- PROFILE_6zhhcaxya0z18
EXEC DBMS_SQLTUNE.UNPACK_STGTAB_SQLPROF(replace=>
true
,staging_table_name =>
'PROFILE_STGTAB'
);
--- if there is no good plan in AWR snaps and you found a good baseline in some other env. and decide to copy here
select * from dba_sql_plan_baselines where plan_name=
'SQL_PLAN_7mduu8xwt7wzx8c7c867d'
;
-- create staging table on source
BEGIN
DBMS_SPM.CREATE_STGTAB_BASELINE (table_name =>
'SPB_86dxp1c32fd42'
,
table_owner =>
'AIUDKC3'
,
tablespace_name =>
'USERS'
);
END;
-- packing SQL baseline to staging table
DECLARE
my_plans NUMBER;
BEGIN
my_plans :=
DBMS_SPM.PACK_STGTAB_BASELINE (
table_name =>
'SPB_86dxp1c32fd42'
,
enabled =>
'yes'
,
table_owner =>
'AIUDKC3'
,
plan_name =>
'SQL_PLAN_7mduu8xwt7wzx8c7c867d'
,
sql_handle =>
'SQL_79b75a477993f3fd'
);
END;
/
select * from SPB_86dxp1c32fd42;
-- export and improt above table
select * from dba_directories where directory_name=
'EXPDP_DUMP'
;
expdp tables=SPB_86dxp1c32fd42 dumpfile=SPB_86dxp1c32fd42.dmp directory=EXPDP_DUMP;
impdp tables=SPB_86dxp1c32fd42 dumpfile=SPB_86dxp1c32fd42.dmp directory=EXPDP_DUMP;
-- unpack sql baseline
/* Formatted on 4/2/2020 10:24:44 AM (QP5 v5.326) */
SET SERVEROUTPUT ON
DECLARE
l_plans_unpacked PLS_INTEGER;
BEGIN
l_plans_unpacked :=
DBMS_SPM.unpack_stgtab_baseline (table_name =>
'SPB_86dxp1c32fd42'
,
table_owner =>
'AIUDKC3'
);
DBMS_OUTPUT.put_line (
'Plans Unpacked: '
|| l_plans_unpacked);
END;
/
select inst_id,plan_hash_value,
'exec sys.DBMS_SHARED_POOL.PURGE ('
''
||ADDRESS||
', '
||HASH_VALUE||
''
', '
'C'
');'
from gV$SQL where sql_id in (
'86dxp1c32fd42'
) order by plan_hash_value;