-- ----------------------------------------------------------------------------------------------
--
-- Script: xplan.sql
--
-- Author: Adrian Billington
--
--
-- Description: Creates a package named XPLAN as a wrapper over DBMS_XPLAN. Provides access to
-- the following DBMS_XPLAN pipelined functions:
--
-- 1\. DISPLAY;
-- 2\. DISPLAY_CURSOR;
-- 3\. DISPLAY_AWR (optional - see Notes section for licence implications).
--
-- The XPLAN wrapper package has one purpose: to include an "order" column in the
-- plan output to show the order in which plan operations are performed. See the
-- following example for details.
--
-- Example: DBMS_XPLAN output (format BASIC):
-- ------------------------------------------------
-- | Id | Operation | Name |
-- ------------------------------------------------
-- | 0 | SELECT STATEMENT | |
-- | 1 | MERGE JOIN | |
-- | 2 | TABLE ACCESS BY INDEX ROWID| DEPT |
-- | 3 | INDEX FULL SCAN | PK_DEPT |
-- | 4 | SORT JOIN | |
-- | 5 | TABLE ACCESS FULL | EMP |
-- ------------------------------------------------
--
-- Equivalent XPLAN output (format BASIC):
-- --------------------------------------------------------
-- | Id | Order | Operation | Name |
-- --------------------------------------------------------
-- | 0 | 6 | SELECT STATEMENT | |
-- | 1 | 5 | MERGE JOIN | |
-- | 2 | 2 | TABLE ACCESS BY INDEX ROWID| DEPT |
-- | 3 | 1 | INDEX FULL SCAN | PK_DEPT |
-- | 4 | 4 | SORT JOIN | |
-- | 5 | 3 | TABLE ACCESS FULL | EMP |
-- --------------------------------------------------------
--
-- Usage: SELECT * FROM TABLE(XPLAN.DISPLAY(...));
-- SELECT * FROM TABLE(XPLAN.DISPLAY_CURSOR(...));
-- SELECT * FROM TABLE(XPLAN.DISPLAY_AWR(...));
--
-- Usage for XPLAN is exactly the same as for DBMS_XPLAN. See the DBMS_XPLAN
-- documentation for all options.
--
-- Note that the only exception to this is that XPLAN.DISPLAY does not contain
-- the FILTER_PREDS parameter available in 10.2+ versions of DBMS_XPLAN.DISPLAY
-- (this parameter enables us to limit the data being returned from an Explain
-- Plan but is of quite limited use).
--
-- See the Notes section for details on the licensing implications of using
-- XPLAN.DISPLAY_AWR.
--
-- Versions: This utility will work for all versions of 10g and upwards.
--
-- Required: 1) PLAN_TABLE of at least 10.1 format
--
-- 2) Either:
-- SELECT ANY DICTIONARY
-- Or:
-- SELECT on V$DATABASE
-- SELECT on V$SQL_PLAN
-- SELECT on V$SESSION
-- SELECT on V$MYSTAT
-- SELECT on DBA_HIST_SQL_PLAN
--
-- 3) CREATE TYPE, CREATE PROCEDURE
--
-- Notes: *** IMPORTANT: PLEASE READ ***
--
-- 1) Oracle license implications
-- ---------------------------
-- The AWR functionality of XPLAN accesses a DBA_HIST% view which means
-- that it requires an Oracle Diagnostic Pack license. The XPLAN.DISPLAY_AWR
-- pipelined function is therefore disabled by default. It can be included
-- by modifying two substitution variables at the start of the script. Please
-- ensure that you are licensed to use this feature: the author accepts
-- no responsibility for any use of this functionality in an unlicensed database.
--
-- Installation: Installation requires SQL*Plus or any IDE that supports substitution
-- variables and SQL*Plus SET commands. To install, simply run the script in
-- the target schema.
--
-- Creates: 1) XPLAN_OT object type
-- 2) XPLAN_NTT collection type
-- 3) XPLAN package
--
-- Removal: 1) DROP PACKAGE xplan;
-- 3) DROP TYPE xplan_ntt;
-- 4) DROP TYPE xplan_ot;
--
--
-- ---------------------------------------------------------------------------------------------- --
-- Define the "commenting-out" substitution variables for the AWR elements of this utility. The
-- default is commented out. To include the AWR functionality, change the variables to " " (i.e.
-- a single space).
-- SET DEFINE ON
DEFINE _awr_start = "/*"
DEFINE _awr_end = "*/" --
-- Supporting types for the pipelined functions...
-- CREATE OR REPLACE TYPE xplan_ot AS OBJECT( plan_table_output VARCHAR2(300) );
/ CREATE OR REPLACE TYPE xplan_ntt AS TABLE OF xplan_ot;
/ --
-- Xplan package...
-- CREATE OR REPLACE PACKAGE xplan AS FUNCTION display( p_table_name IN VARCHAR2 DEFAULT 'PLAN_TABLE',
p_statement_id IN VARCHAR2 DEFAULT NULL,
p_format IN VARCHAR2 DEFAULT 'TYPICAL' )
RETURN xplan_ntt PIPELINED; FUNCTION display_cursor( p_sql_id IN VARCHAR2 DEFAULT NULL,
p_cursor_child_no IN INTEGER DEFAULT 0,
p_format IN VARCHAR2 DEFAULT 'TYPICAL' )
RETURN xplan_ntt PIPELINED; &&_awr_start
FUNCTION display_awr( p_sql_id IN VARCHAR2,
p_plan_hash_value IN INTEGER DEFAULT NULL,
p_db_id IN INTEGER DEFAULT NULL,
p_format IN VARCHAR2 DEFAULT 'TYPICAL' )
RETURN xplan_ntt PIPELINED;
&&_awr_end END xplan;
/ CREATE OR REPLACE PACKAGE BODY xplan AS TYPE ntt_order_map_binds IS TABLE OF VARCHAR2(100); TYPE aat_order_map IS TABLE OF PLS_INTEGER
INDEX BY PLS_INTEGER; g_map aat_order_map;
g_hdrs PLS_INTEGER;
g_len PLS_INTEGER;
g_pad VARCHAR2(300); ----------------------------------------------------------------------------
PROCEDURE reset_state IS
BEGIN
g_hdrs := 0;
g_len := 0;
g_pad := NULL;
g_map.DELETE;
END reset_state; ----------------------------------------------------------------------------
PROCEDURE build_order_map( p_sql IN VARCHAR2,
p_binds IN ntt_order_map_binds ) IS TYPE rt_id_data IS RECORD
( id PLS_INTEGER
, ord PLS_INTEGER ); TYPE aat_id_data IS TABLE OF rt_id_data
INDEX BY PLS_INTEGER; aa_ids aat_id_data;
v_cursor SYS_REFCURSOR;
v_sql VARCHAR2(32767); BEGIN -- Build SQL template...
-- ---------------------
v_sql := 'WITH sql_plan_data AS ( ' ||
p_sql || '
)
, hierarchical_sql_plan_data AS (
SELECT id
FROM sql_plan_data
START WITH id = 0
CONNECT BY PRIOR id = parent_id
ORDER SIBLINGS BY id DESC
)
SELECT id
, ROW_NUMBER() OVER (ORDER BY ROWNUM DESC) AS ord
FROM hierarchical_sql_plan_data'; -- Binds will differ according to plan type...
-- -------------------------------------------
CASE p_binds.COUNT
WHEN 0
THEN
OPEN v_cursor FOR v_sql;
WHEN 1
THEN
OPEN v_cursor FOR v_sql USING p_binds(1);
WHEN 2
THEN
OPEN v_cursor FOR v_sql USING p_binds(1),
TO_NUMBER(p_binds(2));
WHEN 3
THEN
OPEN v_cursor FOR v_sql USING p_binds(1),
TO_NUMBER(p_binds(2)),
TO_NUMBER(p_binds(3));
END CASE; -- Fetch the ID and order data...
-- ------------------------------
FETCH v_cursor BULK COLLECT INTO aa_ids;
CLOSE v_cursor; -- Populate the order map...
-- -------------------------
FOR i IN 1 .. aa_ids.COUNT LOOP
g_map(aa_ids(i).id) := aa_ids(i).ord;
END LOOP; -- Use the map to determine padding needed to slot in our order column...
-- ----------------------------------------------------------------------
IF g_map.COUNT > 0 THEN
g_len := LEAST(LENGTH(g_map.LAST) + 7, 8);
g_pad := LPAD('-', g_len, '-');
END IF; END build_order_map; ----------------------------------------------------------------------------
FUNCTION prepare_row( p_curr IN VARCHAR2,
p_next IN VARCHAR2 ) RETURN xplan_ot IS v_id PLS_INTEGER;
v_row VARCHAR2(4000);
v_hdr VARCHAR2(64) := '%|%Id%|%Operation%|%'; BEGIN -- Intercept the plan section to include a new column for the
-- the operation order that we mapped earlier. The plan output
-- itself will be bound by the 2nd, 3rd and 4th dashed lines.
-- We need to add in additional dashes, the order column heading
-- and the order value itself...
-- ------------------------------------------------------------- IF p_curr LIKE '---%' THEN IF p_next LIKE v_hdr THEN
g_hdrs := 1;
v_row := g_pad || p_curr;
ELSIF g_hdrs BETWEEN 1 AND 3 THEN
g_hdrs := g_hdrs + 1;
v_row := g_pad || p_curr;
ELSE
v_row := p_curr;
END IF; ELSIF p_curr LIKE v_hdr THEN v_row := REGEXP_REPLACE(
p_curr, '\|',
RPAD('|', GREATEST(g_len-7, 2)) || 'Order |',
1, 2
); ELSIF REGEXP_LIKE(p_curr, '^\|[\* 0-9]+\|') THEN v_id := REGEXP_SUBSTR(p_curr, '[0-9]+');
v_row := REGEXP_REPLACE(
p_curr, '\|',
'|' || LPAD(g_map(v_id), GREATEST(g_len-8, 6)) || ' |',
1, 2
);
ELSE
v_row := p_curr;
END IF; RETURN xplan_ot(v_row); END prepare_row; ----------------------------------------------------------------------------
FUNCTION display( p_table_name IN VARCHAR2 DEFAULT 'PLAN_TABLE',
p_statement_id IN VARCHAR2 DEFAULT NULL,
p_format IN VARCHAR2 DEFAULT 'TYPICAL' )
RETURN xplan_ntt PIPELINED IS v_plan_table VARCHAR2(128) := NVL(p_table_name, 'PLAN_TABLE');
v_sql VARCHAR2(512);
v_binds ntt_order_map_binds := ntt_order_map_binds(); BEGIN reset_state(); -- Prepare the inputs for the order map...
-- ---------------------------------------
v_sql := 'SELECT id, parent_id
FROM ' || v_plan_table || '
WHERE plan_id = (SELECT MAX(plan_id)
FROM ' || v_plan_table || '
WHERE id = 0 %bind%)
ORDER BY id'; IF p_statement_id IS NULL THEN
v_sql := REPLACE(v_sql, '%bind%');
ELSE
v_sql := REPLACE(v_sql, '%bind%', 'AND statement_id = :bv_statement_id');
v_binds := ntt_order_map_binds(p_statement_id);
END IF; -- Build the order map...
-- --------------------------------------------------
build_order_map(v_sql, v_binds); -- Now we can call DBMS_XPLAN to output the plan...
-- ------------------------------------------------
FOR r_plan IN ( SELECT plan_table_output AS p
, LEAD(plan_table_output) OVER (ORDER BY ROWNUM) AS np
FROM TABLE(
DBMS_XPLAN.DISPLAY(
v_plan_table, p_statement_id, p_format
))
ORDER BY
ROWNUM)
LOOP
IF g_map.COUNT > 0 THEN
PIPE ROW (prepare_row(r_plan.p, r_plan.np));
ELSE
PIPE ROW (xplan_ot(r_plan.p));
END IF;
END LOOP; reset_state();
RETURN; END display; ----------------------------------------------------------------------------
FUNCTION display_cursor( p_sql_id IN VARCHAR2 DEFAULT NULL,
p_cursor_child_no IN INTEGER DEFAULT 0,
p_format IN VARCHAR2 DEFAULT 'TYPICAL' )
RETURN xplan_ntt PIPELINED IS v_sql_id v$sql_plan.sql_id%TYPE;
v_child_no v$sql_plan.child_number%TYPE;
v_sql VARCHAR2(256);
v_binds ntt_order_map_binds := ntt_order_map_binds(); BEGIN reset_state(); -- Set a SQL_ID if default parameters passed...
-- --------------------------------------------
IF p_sql_id IS NULL THEN
SELECT prev_sql_id, prev_child_number
INTO v_sql_id, v_child_no
FROM v$session
WHERE sid = (SELECT m.sid FROM v$mystat m WHERE ROWNUM = 1)
AND username IS NOT NULL
AND prev_hash_value <> 0;
ELSE
v_sql_id := p_sql_id;
v_child_no := p_cursor_child_no;
END IF; -- Prepare the inputs for the order mapping...
-- -------------------------------------------
v_sql := 'SELECT id, parent_id
FROM v$sql_plan
WHERE sql_id = :bv_sql_id
AND child_number = :bv_child_no'; v_binds := ntt_order_map_binds(v_sql_id, v_child_no); -- Build the plan order map from the SQL...
-- ----------------------------------------
build_order_map(v_sql, v_binds); -- Now we can call DBMS_XPLAN to output the plan...
-- ------------------------------------------------
FOR r_plan IN ( SELECT plan_table_output AS p
, LEAD(plan_table_output) OVER (ORDER BY ROWNUM) AS np
FROM TABLE(
DBMS_XPLAN.DISPLAY_CURSOR(
v_sql_id, v_child_no, p_format
))
ORDER BY
ROWNUM)
LOOP
IF g_map.COUNT > 0 THEN
PIPE ROW (prepare_row(r_plan.p, r_plan.np));
ELSE
PIPE ROW (xplan_ot(r_plan.p));
END IF;
END LOOP; reset_state();
RETURN; END display_cursor; &_awr_start
----------------------------------------------------------------------------
FUNCTION display_awr( p_sql_id IN VARCHAR2,
p_plan_hash_value IN INTEGER DEFAULT NULL,
p_db_id IN INTEGER DEFAULT NULL,
p_format IN VARCHAR2 DEFAULT 'TYPICAL' )
RETURN xplan_ntt PIPELINED IS v_sql VARCHAR2(256);
v_binds ntt_order_map_binds := ntt_order_map_binds(); BEGIN reset_state(); -- Prepare the SQL for the order mapping...
-- ----------------------------------------
v_sql := 'SELECT id, parent_id
FROM dba_hist_sql_plan
WHERE sql_id = :bv_sql_id
AND plan_hash_value = :bv_plan_hash_value
AND dbid = :bv_dbid'; -- Determine all plans for the sql_id...
-- -------------------------------------
FOR r_awr IN (SELECT DISTINCT
sql_id
, plan_hash_value
, dbid
FROM dba_hist_sql_plan
WHERE sql_id = p_sql_id
AND plan_hash_value = NVL(p_plan_hash_value, plan_hash_value)
AND dbid = NVL(p_db_id, (SELECT dbid FROM v$database))
ORDER BY
plan_hash_value)
LOOP -- Prepare the binds and build the order map...
-- --------------------------------------------
v_binds := ntt_order_map_binds(r_awr.sql_id,
r_awr.plan_hash_value,
r_awr.dbid); -- Build the plan order map from the SQL...
-- ----------------------------------------
build_order_map(v_sql, v_binds); -- Now we can call DBMS_XPLAN to output the plan...
-- ------------------------------------------------
FOR r_plan IN ( SELECT plan_table_output AS p
, LEAD(plan_table_output) OVER (ORDER BY ROWNUM) AS np
FROM TABLE(
DBMS_XPLAN.DISPLAY_AWR(
r_awr.sql_id, r_awr.plan_hash_value,
r_awr.dbid, p_format
))
ORDER BY
ROWNUM)
LOOP
IF g_map.COUNT > 0 THEN
PIPE ROW (prepare_row(r_plan.p, r_plan.np));
ELSE
PIPE ROW (xplan_ot(r_plan.p));
END IF;
END LOOP; END LOOP; reset_state();
RETURN; END display_awr;
&_awr_end END xplan;
/ UNDEFINE _awr_start
UNDEFINE _awr_end

xplan.sql(本脚本获取执行计划显示执行顺序)的更多相关文章

  1. MySQL执行计划显示与执行过程不符合一例

    一 建表和现象的过程如下 CREATE TABLE t1 (id1 INT, a1 INT, b1 INT, PRIMARY KEY(id1));CREATE TABLE t3 (id3 INT UN ...

  2. windows 建立任务执行计划 自动执行脚本

    对于windows服务器网站如果要定时执行脚本,则需要在windows控制面板里找到 管理工具,点击任务计划程序,创建任务填写任务名称 触发器里新建触发条件,设置间隔时间 在操作项,新建触发时需要做的 ...

  3. python脚本利用windows计划定时执行

  4. sql server 数据库优化--显示执行计划

      刚开始用SQL Server的时候,我没有用显示执行计划来对查询进行分析.我曾经一直认为我递交的SQL查询都是最优的,而忽略了查询性能究竟如何,从而对“执行计划”重视不够.在我职业初期,我只要能获 ...

  5. 基于Oracle的SQL优化(崔华著)-整理笔记-第2章“Oracle里的执行计划”

    详细介绍了Oracle数据里与执行计划有关的各个方面的内容,包括执行计划的含义,加何查看执行计划,如何得到目标SQL真实的执行计划,如何查看执行计划的执行顺序,Oracle数据库里各种常见的执行计划的 ...

  6. 执行计划sql

    我准备开始分析并优化我的查询.在分析之前,我想到了一些问题. MS-SQL Server什么时候使用"Table Scan"? MS-SQL Server什么时候使用"I ...

  7. SQL执行计划之sql_trace

    一,sql_trace的作用:用以描述SQL的执行过程的trace输出.      - SQL是如何操作数据的      - SQL执行过程中产生了哪些等待事件      - SQL执行中消耗了多少资 ...

  8. Atitit sql执行计划

    Atitit sql执行计划 1.1. 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的 Oracle中的执行计划 ...

  9. SQL Server索引进阶:第九级,读懂执行计划

    原文地址: Stairway to SQL Server Indexes: Level 9,Reading Query Plans 本文是SQL Server索引进阶系列(Stairway to SQ ...

随机推荐

  1. 多Form界面控件状态变化问题分析

    假定有frmA,frmB,frmC三个界面,当frmA中触发显示frmC与frmB触发显示frmC时显示界面不同,或者让frmC上的某个按钮不可用,此时应该在如何来控制frmC的显示.是采用在frmC ...

  2. 关于MySQL的wait_timeout连接超时问题报错解决方案

    bug回顾 : 想必大家在用MySQL时都会遇到连接超时的问题,如下图所示: ### Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsExce ...

  3. 关于编写性能高效的javascript事件的技术

    如何能做出高效的web前端程序是我每次做前端开发都会不自觉去考虑的问题.几年前雅虎里牛逼的前端工程师们出了一本关于提升web前端性能的书籍,轰动了整个web开发技术界,让神秘的web前端优化问题成为了 ...

  4. Find and delete duplicate files

    作用:查找指定目录(一个或多个)及子目录下的所有重复文件,分组列出,并可手动选择或自动随机删除多余重复文件,每组重复文件仅保留一份.(支持文件名有空格,例如:"file  name" ...

  5. 兼容好的JS图片上传预览代码

    转 : http://www.codefans.net/articles/1395.shtml 兼容好的JS图片上传预览代码 (谷歌,IE11) <html xmlns="http:/ ...

  6. 用swing也可以做出好看的界面

    用Swing做出的例子:JavaFX做出的界面:后来又做出了自己编写的一套基于Synth的L&F,其与直接在代码中重绘某个组件不同,最大优点是具有可插拔性,即在不改变原有程序代码的情况下,用户 ...

  7. Autoit3 获取WinForm下的ToolTip

    相比Autohotkey,在我看来,Autoit最实用的就是对于WinForm Application的良好支持 然而,要想将鼠标放在WinForm的ToolTip上,简直无异于自己把自己举起来,故而 ...

  8. Spring Boot 乐观锁加锁失败 - 使用AOP恢复错误

    之前写了一些辅助工作相关的Spring Boot怎么使用AOP.这里继续正题,怎么减少Spring Boot 乐观锁加锁报错的情况(基本可以解决). 1. 包依赖 spring-boot-starte ...

  9. mybatis配置自带缓存和第三方缓存

    http://blog.csdn.net/grhlove123/article/details/47808025

  10. Activity系列讲解---数据传递

    在Android中,不同的Activity实例可能运行在一个进程中,也可能运行在不同的进程中.因此需要一种特别的机制帮助我们在Activity之间传递消息.Android中通过Intent对象来表示一 ...