197 lines
7.8 KiB
SQL
197 lines
7.8 KiB
SQL
----------------------------------------------------------------------------------------
|
|
--
|
|
-- File name: cs_spch_scan_create.sql
|
|
--
|
|
-- Purpose: Create a SQL Patch for slow KIEV performScanQuery without Baselines, Profiles and Patches
|
|
-- (if milliseconds per row processed > 1)
|
|
--
|
|
-- Author: Carlos Sierra
|
|
--
|
|
-- Version: 2023/02/10
|
|
--
|
|
-- Usage: Connecting into PDB.
|
|
--
|
|
-- Example: $ sqlplus / as sysdba
|
|
-- SQL> @cs_spch_scan_create.sql
|
|
--
|
|
-- Notes: Developed and tested on 12.1.0.2.
|
|
--
|
|
---------------------------------------------------------------------------------------
|
|
--
|
|
@@cs_internal/cs_primary.sql
|
|
@@cs_internal/cs_cdb_warn.sql
|
|
@@cs_internal/cs_set.sql
|
|
@@cs_internal/cs_def.sql
|
|
@@cs_internal/cs_file_prefix.sql
|
|
--
|
|
DEF cs_script_name = 'cs_spch_scan_create';
|
|
DEF hints_text = "FIRST_ROWS(1) OPT_PARAM(''_fix_control'' ''5922070:OFF'')";
|
|
--
|
|
SELECT '&&cs_file_prefix._&&cs_script_name.' cs_file_name FROM DUAL;
|
|
--
|
|
@@cs_internal/cs_spool_head.sql
|
|
PRO SQL> @&&cs_script_name..sql
|
|
@@cs_internal/cs_spool_id.sql
|
|
--
|
|
COL et_ms_per_exec FOR 999,990 HEA 'ET|ms p/e';
|
|
COL cpu_ms_per_exec FOR 999,990 HEA 'CPU|ms p/e';
|
|
COL io_ms_per_exec FOR 999,990 HEA 'I/O|ms p/e';
|
|
COL appl_ms_per_exec FOR 999,990 HEA 'Appl|ms p/e';
|
|
COL conc_ms_per_exec FOR 999,990 HEA 'Conc|ms p/e';
|
|
COL execs FOR 999,990 HEA 'Execs';
|
|
COL rows_per_exec FOR 999,999,990 HEA 'Rows|p/e';
|
|
COL gets_per_exec FOR 999,999,990 HEA 'Buffer Gets|p/e';
|
|
COL reads_per_exec FOR 9,999,990 HEA 'Disk Rs|p/e';
|
|
COL writes_per_exec FOR 999,990 HEA 'Dir Wr|p/e';
|
|
COL fetches_per_exec FOR 999,990 HEA 'Fetches|p/e';
|
|
COL sql_text FOR A60 TRUNC;
|
|
COL plan_hash_value FOR 9999999999 HEA 'Plan Hash';
|
|
COL has_baseline FOR A2 HEA 'BL';
|
|
COL has_profile FOR A2 HEA 'PR';
|
|
COL has_patch FOR A2 HEA 'PA';
|
|
COL line FOR A500;
|
|
--
|
|
PRO
|
|
PRO KIEV performScanQuery Latency (as per last &&cs_last_snap_mins. minutes)
|
|
PRO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
WITH
|
|
sqlstats AS (
|
|
SELECT /*+ MATERIALIZE NO_MERGE */
|
|
s.delta_elapsed_time/GREATEST(s.delta_execution_count,1)/1e3 AS et_ms_per_exec,
|
|
s.delta_cpu_time/GREATEST(s.delta_execution_count,1)/1e3 AS cpu_ms_per_exec,
|
|
s.delta_user_io_wait_time/GREATEST(s.delta_execution_count,1)/1e3 AS io_ms_per_exec,
|
|
s.delta_application_wait_time/GREATEST(s.delta_execution_count,1)/1e3 AS appl_ms_per_exec,
|
|
s.delta_concurrency_time/GREATEST(s.delta_execution_count,1)/1e3 AS conc_ms_per_exec,
|
|
s.delta_execution_count AS execs,
|
|
s.delta_rows_processed/GREATEST(s.delta_execution_count,1) AS rows_per_exec,
|
|
s.delta_buffer_gets/GREATEST(s.delta_execution_count,1) AS gets_per_exec,
|
|
s.delta_disk_reads/GREATEST(s.delta_execution_count,1) AS reads_per_exec,
|
|
s.delta_direct_writes/GREATEST(s.delta_execution_count,1) AS writes_per_exec,
|
|
s.delta_fetch_count/GREATEST(s.delta_execution_count,1) AS fetches_per_exec,
|
|
s.sql_id,
|
|
s.sql_text,
|
|
s.plan_hash_value,
|
|
s.last_active_child_address
|
|
FROM v$sqlstats s
|
|
WHERE s.delta_elapsed_time > 0
|
|
AND s.sql_text LIKE '/* performScanQuery(%'
|
|
)
|
|
SELECT s.et_ms_per_exec,
|
|
s.cpu_ms_per_exec,
|
|
s.io_ms_per_exec,
|
|
s.appl_ms_per_exec,
|
|
s.conc_ms_per_exec,
|
|
s.execs,
|
|
s.rows_per_exec,
|
|
s.gets_per_exec,
|
|
s.reads_per_exec,
|
|
s.sql_id,
|
|
s.plan_hash_value,
|
|
-- v.has_baseline,
|
|
-- v.has_profile,
|
|
-- v.has_patch,
|
|
s.sql_text
|
|
FROM sqlstats s
|
|
CROSS APPLY (
|
|
SELECT CASE WHEN v.sql_plan_baseline IS NULL THEN 'N' ELSE 'Y' END AS has_baseline,
|
|
CASE WHEN v.sql_profile IS NULL THEN 'N' ELSE 'Y' END AS has_profile,
|
|
CASE WHEN v.sql_patch IS NULL THEN 'N' ELSE 'Y' END AS has_patch
|
|
FROM v$sql v
|
|
WHERE s.plan_hash_value > 0
|
|
AND v.sql_id = s.sql_id
|
|
AND v.plan_hash_value = s.plan_hash_value
|
|
AND v.child_address = s.last_active_child_address
|
|
ORDER BY
|
|
v.last_active_time DESC
|
|
FETCH FIRST 1 ROW ONLY
|
|
) v
|
|
WHERE v.has_baseline = 'N'
|
|
AND v.has_profile = 'N'
|
|
AND v.has_patch = 'N'
|
|
AND s.et_ms_per_exec / GREATEST(s.rows_per_exec, 1) > 1 -- if milliseconds per row processed > 1
|
|
ORDER BY
|
|
s.et_ms_per_exec DESC
|
|
/
|
|
--
|
|
PRO
|
|
PAUSE Review list above and press "return" key to generate SQL Patch commands
|
|
--
|
|
PRO
|
|
PRO Create SQL Patch commands
|
|
PRO ~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
SET HEA OFF PAGES 0 LIN 500;
|
|
SPO &&cs_file_name._COMMANDS.sql;
|
|
PRO SET ECHO ON;
|
|
WITH
|
|
sqlstats AS (
|
|
SELECT /*+ MATERIALIZE NO_MERGE */
|
|
s.delta_elapsed_time/GREATEST(s.delta_execution_count,1)/1e3 AS et_ms_per_exec,
|
|
s.delta_cpu_time/GREATEST(s.delta_execution_count,1)/1e3 AS cpu_ms_per_exec,
|
|
s.delta_user_io_wait_time/GREATEST(s.delta_execution_count,1)/1e3 AS io_ms_per_exec,
|
|
s.delta_application_wait_time/GREATEST(s.delta_execution_count,1)/1e3 AS appl_ms_per_exec,
|
|
s.delta_concurrency_time/GREATEST(s.delta_execution_count,1)/1e3 AS conc_ms_per_exec,
|
|
s.delta_execution_count AS execs,
|
|
s.delta_rows_processed/GREATEST(s.delta_execution_count,1) AS rows_per_exec,
|
|
s.delta_buffer_gets/GREATEST(s.delta_execution_count,1) AS gets_per_exec,
|
|
s.delta_disk_reads/GREATEST(s.delta_execution_count,1) AS reads_per_exec,
|
|
s.delta_direct_writes/GREATEST(s.delta_execution_count,1) AS writes_per_exec,
|
|
s.delta_fetch_count/GREATEST(s.delta_execution_count,1) AS fetches_per_exec,
|
|
s.sql_id,
|
|
s.sql_text,
|
|
s.plan_hash_value,
|
|
s.last_active_child_address,
|
|
SUBSTR(s.sql_text, INSTR(s.sql_text, '(') + 1, INSTR(s.sql_text, ',') - INSTR(s.sql_text, '(') - 1) AS kiev_table_name
|
|
FROM v$sqlstats s
|
|
WHERE s.delta_elapsed_time > 0
|
|
AND s.sql_text LIKE '/* performScanQuery(%'
|
|
)
|
|
SELECT CASE
|
|
WHEN '&&cs_db_version.' > '12.1.0.2.0'
|
|
THEN 'DECLARE'||CHR(10)||'l_name VARCHAR2(1000);'||CHR(10)||'BEGIN'||CHR(10)||
|
|
'l_name := DBMS_SQLDIAG.create_sql_patch(sql_id => '''||s.sql_id||''', hint_text => q''[&&hints_text. LEADING(@SEL$1 '||s.kiev_table_name||')]'', name => ''spch_'||s.sql_id||''', description => q''[&&cs_script_name..sql /*+ &&hints_text. LEADING(@SEL$1 '||s.kiev_table_name||') */ &&cs_reference_sanitized. &&who_am_i.]'');'||CHR(10)|| -- 19c
|
|
'END;'||CHR(10)||'/'
|
|
ELSE 'EXEC DBMS_SQLDIAG_INTERNAL.i_create_patch(sql_id => '''||s.sql_id||''', hint_text => q''[&&hints_text. LEADING(@SEL$1 '||s.kiev_table_name||')]'', name => ''spch_'||s.sql_id||''', description => q''[&&cs_script_name..sql /*+ &&hints_text. LEADING(@SEL$1 '||s.kiev_table_name||') */ &&cs_reference_sanitized. &&who_am_i.]'');' -- 12c
|
|
END||CHR(10) AS line
|
|
FROM sqlstats s
|
|
CROSS APPLY (
|
|
SELECT CASE WHEN v.sql_plan_baseline IS NULL THEN 'N' ELSE 'Y' END AS has_baseline,
|
|
CASE WHEN v.sql_profile IS NULL THEN 'N' ELSE 'Y' END AS has_profile,
|
|
CASE WHEN v.sql_patch IS NULL THEN 'N' ELSE 'Y' END AS has_patch
|
|
FROM v$sql v
|
|
WHERE s.plan_hash_value > 0
|
|
AND v.sql_id = s.sql_id
|
|
AND v.plan_hash_value = s.plan_hash_value
|
|
AND v.child_address = s.last_active_child_address
|
|
ORDER BY
|
|
v.last_active_time DESC
|
|
FETCH FIRST 1 ROW ONLY
|
|
) v
|
|
WHERE v.has_baseline = 'N'
|
|
AND v.has_profile = 'N'
|
|
AND v.has_patch = 'N'
|
|
AND s.et_ms_per_exec / GREATEST(s.rows_per_exec, 1) > 1 -- if milliseconds per row processed > 1
|
|
ORDER BY
|
|
s.et_ms_per_exec DESC
|
|
/
|
|
PRO SET ECHO OFF LIN 300;
|
|
SPO OFF;
|
|
HOS chmod 644 &&cs_file_name._COMMANDS.sql
|
|
SET HEA ON PAGES 100;
|
|
--
|
|
PRO
|
|
PAUSE Review list above and press "return" key to execute SQL Patch commands
|
|
--
|
|
-- continues with original spool
|
|
SPO &&cs_file_name..txt APP
|
|
--
|
|
-- execute scripts to create sql patches
|
|
@@&&cs_file_name._COMMANDS.sql
|
|
--
|
|
PRO
|
|
PRO SQL> @&&cs_script_name..sql
|
|
--
|
|
@@cs_internal/cs_spool_tail.sql
|
|
@@cs_internal/cs_undef.sql
|
|
@@cs_internal/cs_reset.sql
|
|
--
|