ACE Director Alum Daniel Morgan, founder of Morgan's Library, is scheduling
complimentary technical Workshops on Database Security for the first 30
Oracle Database customers located anywhere in North America, EMEA, LATAM, or
APAC that send an email to
asra_us@oracle.com. Request a Workshop for
your organization today.
Purpose
Internal utilities supporting the functionality of the DBMS_DIAG and other built-in packages.
This built-in package contains one of the most valuable objects in the Oracle database and while it is a shame that it is not fully documented at docs.oracle.com it has been blogged about by one of the most respected resources in our universe: Maria Colgan.
Look below at the demo of I_CREATE_PATCH and do not underestimate its value.
dbms_sqldiag_internal.i_create_hint_set(
sql_text IN CLOB,
hint_text IN CLOB,
creator IN VARCHAR2,
name IN VARCHAR2,
description IN VARCHAR2,
category IN VARCHAR2,
validate IN BOOLEAN);
TBD
Overload 2
dbms_sqldiag_internal.i_create_hint_set(
sql_text IN VARCHAR2,
hint_text IN CLOB,
creator IN VARCHAR2,
name IN VARCHAR2,
description IN VARCHAR2,
category IN VARCHAR2,
validate IN BOOLEAN);
Patches SQL statements inside the CBO by inserting a hint
This syntax is valid in 12.1.0.2 but not in 12.2.0.1 which is the two overloads below.
Overload 1, Example 1
dbms_sqldiag_internal.i_create_patch(
sql_text IN CLOB,
hint_text IN VARCHAR2,
name IN VARCHAR2,
description IN VARCHAR2,
category IN VARCHAR2,
validate IN BOOLEAN);
/* the following demo was written and published by Maria Colgan of Oracle. The Library has done some minor reformatting to match the Library standard. */
-- setup script for blog post on SQL Patch
-- Author: Maria Colgan
INSERT INTO emp
WITH tdata AS (
SELECT rownum empno
FROM all_objects
WHERE <= 1000)
SELECT rownum, dbms_random.string ('u', 20), dbms_random.string ('u', 20),
CASE WHEN when rownum/100000 <= 0.001 THEN
MOD(rownum, 10) ELSE 10 END
FROM tdata a, tdata b
WHERE rownum <= 100000;
-- check histogram has been created on DEPTNO (10 buckets)
SELECT column_name, histogram, num_buckets
FROM user_tab_cols
WHERE table_name='EMP';
--declare a value for our bind variable :deptno for our queries
variable deptno number;
exec :deptno := 9
-- begin with a simple query on the emp table without the BIND_AWARE hint. Cursor will not be bind aware
SELECT COUNT(*), MAX(empno)
FROM emp
WHERE deptno = :deptno;
-- add a BIND_AWARE hint and execute again.
-- this time the cursor will be marked bind aware immediately
SELECT /*+ BIND_AWARE */ COUNT(*), MAX(empno)
FROM emp
WHERE deptno = :deptno;
-- check in v$SQL we will see two cursors one IS_BIND_AWARE and one that is not
SELECT sql_id, substr(sql_text,1,40), executions, is_bind_aware
FROM v$sql
WHERE sql_id IN ('09a1uvyty82b1', '4j5y55fd5rx77');
-- create a SQL patch for the query
conn sys@pdbdev as sysdba
BEGIN
sys.dbms_sqldiag_internal.i_create_patch(
sql_text => 'SELECT COUNT(*), MAX(empno) FROM emp WHERE deptno = :deptno',
hint_text => 'BIND_AWARE',
name => 'test_patch');
END;
/
conn sh/sh@pdbdev
-- check the SQL patch is working
SELECT COUNT(*), MAX(empno)
FROM emp
WHERE deptno = :deptno;
SELECT sql_id, substr(sql_text,1,40), executions, is_bind_aware
FROM v$sql
WHERE sql_id IN ('09a1uvyty82b1', '4j5y55fd5rx77');
-- try a different SQL statement this time and add a different hint
explain plan for
SELECT COUNT(*), MAX(empno)
FROM (
SELECT *
FROM emp
WHERE deptno = 10);
SELECT * FROM TABLE(dbms_xplan.display(format=>'basic +note'));
-- the initial plan shows a FTS we want an index access so lets add a hint
EXPLAIN PLAN FOR
SELECT /*+ INDEX(@SEL$2 emp) */ COUNT(*), MAX(empno)
FROM (SELECT * FROM emp WHERE deptno = 10);
SELECT * FROM TABLE(dbms_xplan.display(format=>'basic +note'));
-- we have the plan we want lets create a SQL patch for it
conn sys@pdbdev as sysdba
BEGIN
sys.dbms_sqldiag_internal.i_create_patch(
sql_text => 'SELECT COUNT(*), MAX(empno) FROM (SELECT * FROM emp WHERE deptno = 10)',
hint_text => 'INDEX(@SEL$2 emp)',
name => 'test_patch2');
END;
/
conn sh/sh@pdbdev
--see if the SQL patch has an effect
EXPLAIN PLAN FOR
SELECT COUNT(*), MAX(empno)
FROM (
SELECT *
FROM emp
WHERE deptno = 10);
SELECT * FROM TABLE(dbms_xplan.display(format=>'basic +note'));
With the exception of the CREATOR column appears to map to DBMS_SQLDIAG.CREATE_SQL_PATCH
overload 2, below
Overload 1, Example 2
dbms_sqldiag_internal.i_create__patch(
sql_id IN VARCHAR2,
hint_text IN CLOB,
creator IN VARCHAR2,
name IN VARCHAR2,
description IN VARCHAR2,
category IN VARCHAR2,
validate IN BOOLEAN)
RETURN VARCHAR2;
TBD
With the exception of the CREATOR column appears to map to DBMS_SQLDIAG.CREATE_SQL_PATCH overload 1
Overload 2
dbms_sqldiag_internal.i_create__patch(
sql_text IN CLOB,
hint_text IN CLOB,
creator IN VARCHAR2 := NULL,
decription IN VARCHAR2 := NULL,
category IN VARCHAR2 := NULL,
validate IN BOOLEAN := TRUE)
RETURN VARCHAR2;
Returns the optimizer parameters for a SQL Plan Management baseline
dbms_sqldiag_internal.i_generate_param_import(l_sql_id IN VARCHAR2) RETURN VARCHAR2;
SELECT DISTINCT sql_id
FROM v$sql
WHERE rownum < 11;
SELECT * FROM TABLE(dbms_xplan.display_cursor('gd90ygn1j4026'));
----------------------------------------------------------------------------
| Id | Operation | Name |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| OPT_FINDING_OBJ$ |
|* 2 | INDEX RANGE SCAN | I_OPT_FINDING_OBJ_ID_OBJ_TYPE |
----------------------------------------------------------------------------
SELECT dbms_sqldiag_internal.i_generate_param_import('gd90ygn1j4026')
FROM dual;
DBMS_SQLDIAG_INTERNAL.I_GENERATE_PARAM_IMPORT('GD90YGN1J4026')
------------------------------------------------------------------
alter session set "optimizer_capture_sql_plan_baselines" = true;
alter session set "optimizer_index_caching" = 50;
alter session set "optimizer_index_cost_adj" = 50;
alter session set "optimizer_mode" = choose;
dbms_sqldiag_internal.i_get_incident_for_sqlid(
sql_id IN VARCHAR2,
problem_type IN NUMBER,
incident_id OUT NUMBER);
DECLARE
outVal NUMBER;
BEGIN
dbms_sqldiag_internal.i_get_incident_for_sqlid('6ayccp4h1n07f', 1, outVal);
dbms_output.put_line(outVal);
END;
/
DECLARE
*
ERROR at line 1:
ORA-24801: illegal parameter value in OCI lob function
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 247
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 303
ORA-06512: at "SYS.DBMS_SQLDIAG", line 1329
ORA-06512: at "SYS.DBMS_SQLDIAG", line 1364
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 637
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 637
ORA-06512: at line 4
dbms_sqldiag_internal.i_incidentid_2_sql(
incident_id IN VARCHAR2,
sql_stmt OUT sqlset_row,
problem_type OUT NUMBER,
err_code OUT BINARY_INTEGER,
err_mesg OUT VARCHAR2,
exec_user_id OUT NUMBER);
DECLARE
sqlOut sqlset_row;
probOut NUMBER;
ecode BINARY_INTEGER;
emesg VARCHAR2(120);
exuid NUMBER;
BEGIN
dbms_sqldiag_internal.i_incidentid_2_sql(72130, sqlOut, probOut, ecode, emesg, exuid);
dbms_output.put_line(probOut);
dbms_output.put_line(ecode);
dbms_output.put_line(emesg);
dbms_output.put_line(exuid);
END;
/
DECLARE
*
ERROR at line 1:
ORA-24801: illegal parameter value in OCI lob function
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 247
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 303
ORA-06512: at line 8
SELECT dbms_sqldiag_internal.i_validate_problem_type(99)
FROM dual;
SELECT
dbms_sqldiag_internal.i_validate_problem_type(5)
*
ERROR at line 1:
ORA-13796: invalid value 5 specified for problem type
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 86
ORA-06512: at "SYS.DBMS_SQLDIAG_INTERNAL", line 591'