---------------------------------------------------------------------------------------- -- -- File name: cs_sprf_indexes.sql -- -- Purpose: List of Indexes Referenced by all SQL Profiles on PDB -- -- Author: Carlos Sierra -- -- Version: 2022/07/29 -- -- Usage: Connecting into PDB. -- -- Example: $ sqlplus / as sysdba -- SQL> @cs_sprf_indexes.sql -- -- Notes: Developed and tested on 19c. -- -- ORA-00600: internal error code, arguments: [qkebCreateColInFro:1], [], [], [], [], [], [], [], [], [], [], [] -- see bug 31947732 -- --------------------------------------------------------------------------------------- -- @@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_sprf_indexes'; -- 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 sql_id FOR A13; COL signature FOR 99999999999999999999; COL sql_handle FOR A20; COL plan_name FOR A30; COL plan_id FOR 9999999999; -- COL plan_hash FOR 9999999999; -- COL plan_hash2 FOR 9999999999; -- COL plan_hash_full FOR 9999999999; COL indexed_columns FOR A200; COL table_owner FOR A30; COL table_name FOR A30; COL index_owner FOR A30; COL index_name FOR A30; COL sql_text FOR A100 TRUNC; COL description FOR A100 TRUNC; COL created FOR A23; COL last_modified FOR A23; COL last_executed FOR A23; COL timestamp FOR A19; -- -- only works from PDB. do not use CONTAINERS(table_name) since it causes ORA-00600: internal error code, arguments: [kkdolci1], [], [], [], [], [], [], WITH FUNCTION compute_sql_id (sql_text IN CLOB) RETURN VARCHAR2 IS BASE_32 CONSTANT VARCHAR2(32) := '0123456789abcdfghjkmnpqrstuvwxyz'; l_raw_128 RAW(128); l_hex_32 VARCHAR2(32); l_low_16 VARCHAR(16); l_q3 VARCHAR2(8); l_q4 VARCHAR2(8); l_low_16_m VARCHAR(16); l_number NUMBER; l_idx INTEGER; l_sql_id VARCHAR2(13); function_returned_an_error EXCEPTION; PRAGMA EXCEPTION_INIT(function_returned_an_error, -28817); -- ORA-28817: PL/SQL function returned an error. BEGIN l_raw_128 := /* use md5 algorithm on sql_text and produce 128 bit hash */ SYS.DBMS_CRYPTO.hash(TRIM(CHR(0) FROM sql_text)||CHR(0), SYS.DBMS_CRYPTO.hash_md5); l_hex_32 := RAWTOHEX(l_raw_128); /* 32 hex characters */ l_low_16 := SUBSTR(l_hex_32, 17, 16); /* we only need lower 16 */ l_q3 := SUBSTR(l_low_16, 1, 8); /* 3rd quarter (8 hex characters) */ l_q4 := SUBSTR(l_low_16, 9, 8); /* 4th quarter (8 hex characters) */ /* need to reverse order of each of the 4 pairs of hex characters */ l_q3 := SUBSTR(l_q3, 7, 2)||SUBSTR(l_q3, 5, 2)||SUBSTR(l_q3, 3, 2)||SUBSTR(l_q3, 1, 2); l_q4 := SUBSTR(l_q4, 7, 2)||SUBSTR(l_q4, 5, 2)||SUBSTR(l_q4, 3, 2)||SUBSTR(l_q4, 1, 2); /* assembly back lower 16 after reversing order on each quarter */ l_low_16_m := l_q3||l_q4; /* convert to number */ SELECT TO_NUMBER(l_low_16_m, 'xxxxxxxxxxxxxxxx') INTO l_number FROM DUAL; /* 13 pieces base-32 (5 bits each) make 65 bits. we do have 64 bits */ FOR i IN 1 .. 13 LOOP l_idx := TRUNC(l_number / POWER(32, (13 - i))); /* index on BASE_32 */ l_sql_id := l_sql_id||SUBSTR(BASE_32, (l_idx + 1), 1); /* stitch 13 characters */ l_number := l_number - (l_idx * POWER(32, (13 - i))); /* for next piece */ END LOOP; RETURN l_sql_id; EXCEPTION WHEN function_returned_an_error THEN RETURN 'ORA-28817'; END compute_sql_id; i AS ( SELECT /*+ MATERIALIZE NO_MERGE */ ic.table_owner, ic.table_name, ic.index_owner, ic.index_name, LISTAGG('"'||ic.table_name||'"."'||ic.column_name||'"', ' ' ON OVERFLOW TRUNCATE) WITHIN GROUP (ORDER BY ic.column_position) AS indexed_columns FROM dba_ind_columns ic WHERE ROWNUM >= 1 /* NO_MERGE */ GROUP BY ic.table_owner, ic.table_name, ic.index_owner, ic.index_name ), b AS ( SELECT /*+ MATERIALIZE NO_MERGE */ p.signature, t.sql_handle, o.name AS plan_name, p.plan_id, -- TO_NUMBER(EXTRACTVALUE(XMLTYPE(p.comp_data),'/*/info[@type = "plan_hash"]')) AS plan_hash, -- normal plan_hash_value -- TO_NUMBER(EXTRACTVALUE(XMLTYPE(p.comp_data),'/*/info[@type = "plan_hash_2"]')) AS plan_hash_2, -- plan_hash_value ignoring transient object names (must be same than plan_id for a baseline to be used) -- TO_NUMBER(EXTRACTVALUE(XMLTYPE(p.comp_data),'/*/info[@type = "plan_hash_full"]')) AS plan_hash_full, -- adaptive plan (must be different than plan_hash_2 on loaded plans) DECODE(BITAND(o.flags, 1), 0, 'NO', 'YES') AS enabled, -- DECODE(BITAND(o.flags, 2), 0, 'NO', 'YES') AS accepted, -- DECODE(BITAND(o.flags, 4), 0, 'NO', 'YES') AS fixed, -- DECODE(BITAND(o.flags, 64), 0, 'YES', 'NO') AS reproduced, -- DECODE(BITAND(o.flags, 128), 0, 'NO', 'YES') AS autopurge, -- DECODE(BITAND(o.flags, 256), 0, 'NO', 'YES') AS adaptive, SUBSTR(x.outline_hint, INSTR(x.outline_hint, '(', 1, 2) + 1, INSTR(x.outline_hint, '))') - INSTR(x.outline_hint, '(', 1, 2) - 1) AS indexed_columns, t.sql_text, a.description, a.origin, a.created, a.last_modified, o.last_executed, TO_DATE(NULL) AS timestamp FROM sys.sqlobj$data p, XMLTABLE('outline_data/hint' PASSING XMLTYPE(p.comp_data) COLUMNS outline_hint VARCHAR2(500) PATH '.') x, sys.sqlobj$ o, sys.sqlobj$auxdata a, sys.sql$text t WHERE 1 = 1 -- p.signature = 16223414913647067245 AND p.category = 'DEFAULT' AND p.obj_type = 1 /* 1:profile, 2:baseline, 3:patch */ AND p.comp_data IS NOT NULL AND x.outline_hint LIKE 'INDEX%(%(%))' AND o.signature = p.signature AND o.category = p.category AND o.obj_type = p.obj_type AND o.plan_id = p.plan_id AND a.signature = o.signature AND a.category = o.category AND a.obj_type = o.obj_type AND a.plan_id = o.plan_id AND t.signature = p.signature AND ROWNUM >= 1 /* NO_MERGE */ ), x AS ( SELECT /*+ MATERIALIZE NO_MERGE */ DISTINCT compute_sql_id(b.sql_text) AS sql_id, b.sql_handle, b.plan_name, b.plan_id, -- b.plan_hash, -- b.plan_hash_2, -- b.plan_hash_full, b.enabled, -- b.accepted, -- b.fixed, -- b.reproduced, -- b.autopurge, -- b.adaptive, b.indexed_columns, NVL(i.table_owner, '"missing"') AS table_owner, NVL(i.table_name, '"missing"') AS table_name, NVL(i.index_owner, '"missing"') AS index_owner, NVL(i.index_name, '"missing"') AS index_name, DBMS_LOB.SUBSTR(b.sql_text, 1000) AS sql_text, b.description, b.created, b.last_modified, b.last_executed, b.timestamp FROM b, i WHERE i.indexed_columns(+) = b.indexed_columns AND ROWNUM >= 1 /* NO_MERGE */ ) SELECT /* comment out unwanted columns */ x.sql_id, x.sql_text, -- x.sql_handle, x.plan_name, -- x.plan_id, -- x.plan_hash, -- x.plan_hash_2, -- x.plan_hash_full, x.enabled, -- x.accepted, -- x.fixed, -- x.reproduced, -- x.autopurge, -- x.adaptive, x.indexed_columns, x.table_owner, x.table_name, x.index_owner, x.index_name, -- x.created, -- x.last_modified, -- x.last_executed, -- x.timestamp, x.description FROM x ORDER BY x.sql_id, x.plan_name, x.indexed_columns, x.table_owner, x.table_name, x.index_owner, x.index_name / -- PRO PRO SQL> @&&cs_script_name..sql -- @@cs_internal/cs_spool_tail.sql @@cs_internal/cs_undef.sql @@cs_internal/cs_reset.sql --