Skip to Main Content

Oracle Database Discussions

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

How can we identify and set up an alert mechanism whenever a good execution plan changes to a bad one

0614Nov 22 2024

Hi folks,

Question:
How can we effectively use gv$sql when a SQL query has multiple plan hash values, and how can we compare the performance between them if we observe multiple records within a 10-minute interval?

Example:
Consider the sql_id ABCV6574gh, which had four different plan hash values over the last 10 minutes, with the following characteristics:

  • Each plan hash value executed 10 times.
  • One plan ran in 0.01 seconds per execution (good plan).
  • Two plans took 0.04 seconds per execution.
  • The last plan ran in 4 seconds per execution (bad plan).

In this scenario, the plan with 4 seconds execution time would be identified as a bad plan, while the plan with 0.01 seconds execution time would be the good plan. Based on this, I would apply a SQL profile to enforce the first plan hash value for consistent performance.

The challenge lies in identifying and comparing these plans efficiently within the 10-minute interval since gv$sql will return multiple records for the same sql_id. How can I implement this process to reliably identify and act upon the good and bad plans, especially when plans shift frequently due to bind peeking, stale statistics, or other factors?

I am trying to identify SQL queries that take more time to execute when their execution plan changes. Additionally, I am tracking these queries in a table at 10-minute intervals. After 10 minutes, I compare the snapshot from the first 10 minutes with the second 10 minutes and publish the results using gv$sqlstats.

However, since gv$sqlstats only retains the latest entry for a given sql_id, I checked gv$sql and found 4–5 entries with different plan hash values. This happens due to reasons such as bind variable changes, stale statistics, or other factors.

My primary goal is to identify SQL queries that have shifted from a good plan to a bad plan within the last 20 minutes. I want to repeat this process throughout the day. By identifying and fixing these "hot" SQL queries, I aim to avoid potential business impacts like application downtime or performance degradation

TRUNCATE TABLE appmon.t_sql_execution_monitor;

CREATE OR REPLACE PROCEDURE p_insert_initial_sql_executions AS
v_date DATE := trunc(sysdate, 'MI');
BEGIN
INSERT INTO appmon.t_sql_execution_monitor (
instance_id,
sql_id,
sql_text,
plan_hash_value,
executions,
elapsed_time,
buffer_gets,
last_captured_time
)
SELECT
s.inst_id,
s.sql_id,
s.sql_text,
s.plan_hash_value,
s.executions AS execs,
ROUND(s.elapsed_time / NVL(DECODE(s.executions, 0, 1, s.executions), 1) / 1000000, 3) AS elapsed_time_per_exec,
s.buffer_gets / NVL(DECODE(s.executions, 0, 1, s.executions), 1) AS buffer_gets,
v_date
FROM
gv$sqlstats s,
(
SELECT DISTINCT
sql_id,
l.inst_id
FROM
gv$sql l
WHERE
l.last_active_time >= SYSDATE - INTERVAL '10' MINUTE
AND l.parsing_schema_name NOT IN (
'SYSMON', 'GGSYS', 'DIP', 'ANONYMOUS', 'APPQOSSYS',
'DBSFWUSER', 'APP_ETL', 'APPMON', 'AUDSYS', 'SYS',
'SYSTEM', 'SQLTXADMIN', 'USDBLINK', 'TRCANLZR', 'XDB',
'XPS', 'DBA_REORG', 'DBSNMP', 'ORACLE_OCM', 'GSMADMIN_INTERNAL',
'GSMCATUSER', 'GSMUSER', 'OJVMSYS', 'OUTLN', 'REMOTE_SCHEDULER_AGENT',
'SYSBACKUP', 'SYSDG', 'SYSKM', 'SYSRAC', 'WMSYS',
'SYS$UMF', 'XS$NULL'
)
AND l.plan_hash_value <> 0
) l
WHERE
s.elapsed_time IS NOT NULL
AND s.sql_id = l.sql_id
AND s.inst_id = l.inst_id
AND s.plan_hash_value <> 0
AND (s.elapsed_time / NVL(DECODE(s.executions, 0, 1, s.executions), 1)) > 100000
AND s.last_active_time >= SYSDATE - INTERVAL '10' MINUTE;

COMMIT;
END;
/

Comments