原文链接:https://www.modb.pro/db/23252?cyn (阅读原文,支持作者)

摘要:oracle小工具

  1. 如果一个sql执行计划几十甚至上百行怎么看?本文介绍一个偷懒工具xplan包

利用xplan包可以见到看到执行计划的顺序,如下所示
select * from table(xplan.display_cursor(‘v$sql.sql_id’,0,‘advanced’));

前提是需要执行xplan.package.sql,并做如下授权
SQL> CREATE PUBLIC SYNONYM XPLAN FOR SYS.XPLAN;
SQL> grant execute on sys.xplan to public;

xplan.package.sql内容如下:

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 ASFUNCTION 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_startFUNCTION 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_endEND xplan;
/CREATE OR REPLACE PACKAGE BODY xplan ASTYPE ntt_order_map_binds IS TABLE OF VARCHAR2(100);TYPE aat_order_map IS TABLE OF PLS_INTEGERINDEX BY PLS_INTEGER;g_map  aat_order_map;g_hdrs PLS_INTEGER;g_len  PLS_INTEGER;g_pad  VARCHAR2(300);----------------------------------------------------------------------------PROCEDURE reset_state ISBEGINg_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 ) ISTYPE rt_id_data IS RECORD( id  PLS_INTEGER, ord PLS_INTEGER );TYPE aat_id_data IS TABLE OF rt_id_dataINDEX 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 idFROM   sql_plan_dataSTART WITH id = 0CONNECT BY PRIOR id = parent_idORDER SIBLINGS BY id DESC)SELECT id,      ROW_NUMBER() OVER (ORDER BY ROWNUM DESC) AS ordFROM   hierarchical_sql_plan_data';-- Binds will differ according to plan type...-- -------------------------------------------CASE p_binds.COUNTWHEN 0THENOPEN v_cursor FOR v_sql;WHEN 1THENOPEN v_cursor FOR v_sql USING p_binds(1);WHEN 2THENOPEN v_cursor FOR v_sql USING p_binds(1),TO_NUMBER(p_binds(2));WHEN 3THENOPEN 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 LOOPg_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 THENg_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 ISv_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 '---%' THENIF p_next LIKE v_hdr THENg_hdrs := 1;v_row := g_pad || p_curr;ELSIF g_hdrs BETWEEN 1 AND 3 THENg_hdrs := g_hdrs + 1;v_row := g_pad || p_curr;ELSEv_row := p_curr;END IF;ELSIF p_curr LIKE v_hdr THENv_row := REGEXP_REPLACE(p_curr, '\|',RPAD('|', GREATEST(g_len-7, 2)) || 'Order |',1, 2);ELSIF REGEXP_LIKE(p_curr, '^\|[\* 0-9]+\|') THENv_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);ELSEv_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 ISv_plan_table   VARCHAR2(128) := NVL(p_table_name, 'PLAN_TABLE');v_sql          VARCHAR2(512);v_binds        ntt_order_map_binds := ntt_order_map_binds();BEGINreset_state();-- Prepare the inputs for the order map...-- ---------------------------------------v_sql := 'SELECT id, parent_idFROM   ' || 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 THENv_sql := REPLACE(v_sql, '%bind%');ELSEv_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 npFROM   TABLE(DBMS_XPLAN.DISPLAY(v_plan_table, p_statement_id, p_format))ORDER  BYROWNUM)LOOPIF g_map.COUNT > 0 THENPIPE ROW (prepare_row(r_plan.p, r_plan.np));ELSEPIPE 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 ISv_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();BEGINreset_state();-- Set a SQL_ID if default parameters passed...-- --------------------------------------------IF p_sql_id IS NULL THENSELECT prev_sql_id, prev_child_numberINTO   v_sql_id, v_child_noFROM   v$sessionWHERE  sid = (SELECT m.sid FROM v$mystat m WHERE ROWNUM = 1)AND    username IS NOT NULLAND    prev_hash_value <> 0;ELSEv_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_idFROM   v$sql_planWHERE  sql_id = :bv_sql_idAND    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 npFROM   TABLE(DBMS_XPLAN.DISPLAY_CURSOR(v_sql_id, v_child_no, p_format))ORDER  BYROWNUM)LOOPIF g_map.COUNT > 0 THENPIPE ROW (prepare_row(r_plan.p, r_plan.np));ELSEPIPE 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 ISv_sql      VARCHAR2(256);v_binds    ntt_order_map_binds := ntt_order_map_binds();BEGINreset_state();-- Prepare the SQL for the order mapping...-- ----------------------------------------v_sql := 'SELECT id, parent_idFROM   dba_hist_sql_planWHERE  sql_id = :bv_sql_idAND    plan_hash_value = :bv_plan_hash_valueAND    dbid = :bv_dbid';-- Determine all plans for the sql_id...-- -------------------------------------FOR r_awr IN (SELECT DISTINCTsql_id,      plan_hash_value,      dbidFROM   dba_hist_sql_planWHERE  sql_id = p_sql_idAND    plan_hash_value = NVL(p_plan_hash_value, plan_hash_value)AND    dbid = NVL(p_db_id, (SELECT dbid FROM v$database))ORDER  BYplan_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 npFROM   TABLE(DBMS_XPLAN.DISPLAY_AWR(r_awr.sql_id, r_awr.plan_hash_value,r_awr.dbid, p_format))ORDER  BYROWNUM)LOOPIF g_map.COUNT > 0 THENPIPE ROW (prepare_row(r_plan.p, r_plan.np));ELSEPIPE ROW (xplan_ot(r_plan.p));END IF;END LOOP;END LOOP;reset_state();RETURN;END display_awr;
&_awr_endEND xplan;
/UNDEFINE _awr_start
UNDEFINE _awr_end

效果展示:
select SQL_ID from v$sqlarea where SQL_TEXT like ‘%select * from scott.emp e,scott.dept d where e.deptno=d.deptno and sal>1000%’;

SQL_ID

6fcx62gg7ph2a
6hw8sn0cb1rm6

select * from table(xplan.display_cursor(‘6hw8sn0cb1rm6’,0,‘advanced’));

PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  6hw8sn0cb1rm6, child number 0
-------------------------------------
select * from scott.emp e,scott.dept d where e.deptno=d.deptno and
sal>1000Plan hash value: 844388907------------------------------------------------------------------------------------------------
| Id  | Order | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 |     6 | SELECT STATEMENT             |         |       |       |     6 (100)|          |
|   1 |     5 |  MERGE JOIN                  |         |    13 |   754 |     6  (17)| 00:00:01 |
|   2 |     2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    80 |     2   (0)| 00:00:01 |
|   3 |     1 |    INDEX FULL SCAN           | PK_DEPT |     4 |       |     1   (0)| 00:00:01 |
|*  4 |     4 |   SORT JOIN                  |         |    13 |   494 |     4  (25)| 00:00:01 |
|*  5 |     3 |    TABLE ACCESS FULL         | EMP     |    13 |   494 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------Query Block Name / Object Alias (identified by operation id):
---------------------------------------------------------------------1 - SEL$12 - SEL$1 / D@SEL$13 - SEL$1 / D@SEL$15 - SEL$1 / E@SEL$1Outline Data
-------------/*+BEGIN_OUTLINE_DATAIGNORE_OPTIM_EMBEDDED_HINTSOPTIMIZER_FEATURES_ENABLE('11.2.0.4')DB_VERSION('11.2.0.4')ALL_ROWSOUTLINE_LEAF(@"SEL$1")INDEX(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))FULL(@"SEL$1" "E"@"SEL$1")LEADING(@"SEL$1" "D"@"SEL$1" "E"@"SEL$1")USE_MERGE(@"SEL$1" "E"@"SEL$1")PX_JOIN_FILTER(@"SEL$1" "E"@"SEL$1")END_OUTLINE_DATA*/Predicate Information (identified by operation id):
---------------------------------------------------4 - access("E"."DEPTNO"="D"."DEPTNO")filter("E"."DEPTNO"="D"."DEPTNO")5 - filter("SAL">1000)Column Projection Information (identified by operation id):
-----------------------------------------------------------1 - "D"."DEPTNO"[NUMBER,22], "E"."DEPTNO"[NUMBER,22],"D"."LOC"[VARCHAR2,13], "D"."DNAME"[VARCHAR2,14], "E"."EMPNO"[NUMBER,22],"E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22],"E"."HIREDATE"[DATE,7], "SAL"[NUMBER,22], "E"."COMM"[NUMBER,22]2 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]3 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]4 - (#keys=1) "E"."DEPTNO"[NUMBER,22], "E"."EMPNO"[NUMBER,22],"E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22],"E"."HIREDATE"[DATE,7], "SAL"[NUMBER,22], "E"."COMM"[NUMBER,22]5 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],"E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "SAL"[NUMBER,22],"E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]67 rows selected.

更多Oracle优化资讯:https://www.modb.pro/tag/oracle?cyn

懒人看执行计划神器 for Oracle相关推荐

  1. oracle 从执行计划的预估行数看执行计划是否正确

    oracle 从执行计划的预估行数看执行计划是否正确 从执行计划的预估行数可以看出执行计划是否正确,作为优化的你曾经注意到了么? 今天在监控系统垃圾sql语句的时候发现一个sql语句跑了10个小时了, ...

  2. 从执行计划的预估行数看执行计划是否正确

    从执行计划的预估行数可以看出执行计划是否正确,作为优化的你曾经注意到了么? 今天在监控系统垃圾sql语句的时候发现一个sql语句跑了10个小时了,凭直觉这个sql肯定哪里出现问题了,好吧,老规矩,先看 ...

  3. oracle执行计划time单位,Oracle中查看执行计划

    方法一.通过使用工具PLSQL Developer中的Explain Plan Window窗口查看SQL执行计划.具体参考 方法二.通过SQL*PLUS中的autotrace命令查看 1.登录拥有d ...

  4. 查询优化器内核剖析第四篇:从一个实例看执行计划

    查询优化器内核剖析第四篇:从一个实例看执行计划 系列文章索引: 查询优化器内核剖析第一篇 查询优化器内核剖析第二篇:产生候选执行计划&执行计划成本估算 查询优化器内核剖析第三篇:查询的执行与计 ...

  5. oracle 产看执行计划_ODBA 技能SPM计划

    OBA技能1-获取执行计划 OBA技能2-执行计划顺序 OBA技能3-执行计划顺序表连接 ODBA 技能4实战执行计划 ODBA 技能5 固定执行计划 因为每次统计信息作业在收集完信息后,会触发ACS ...

  6. oracle执行计划案例,返璞归真 - Oracle 9i的RBO执行计划案例

    预计阅读时间:15分钟 最近配合DBA团队,做了一次Oracle 9i老旧应用的搬迁工作,偶然发现应用某一个逻辑,执行缓慢,进而根据代码,找到对应的SQL语句,分析过程,还是有些意思,也暴露了些问题. ...

  7. 海天、李锦记试水“懒人调料”,做饭神器究竟有多神?

    来源 | 螳螂观察 文 | 陈三 年轻人的一个"懒"字,不知道造就了多少个行业风口. 这不,如今正如火如荼进行的千亿外卖项目就是由其"懒得做饭"而起. 去年,易 ...

  8. mysql 导入百万级数据 几种 java_Java 修行第034天--执行计划及其使用--Oracle数据导入导出--第三章MySQL使用...

    执行计划中牢记几句话: -- 尽量避免是*代替所有列,编写查询语句时使用具体列名代替*,可以防止全表扫描 -- 尽可能少的使用like关键字进行模糊查询 -- 建立适当的索引可以提高查询效率 十三. ...

  9. oracle执行计划cost单位,Oracle 执行计划(5)—cost成本之索引范围扫描-B树索引

    Oracle 执行计划(5)-cost成本之索引范围扫描-B树索引 SQL>  select * from t1 where a<600 ; 已选择599行. 已用时间:  00: 00: ...

最新文章

  1. ios辅助功能之voiceover实战
  2. 【ZooKeeper Notes 9】ZooKeepr日志清理
  3. 剑指offer五:两个栈实现一个队列
  4. 六十八、SpringBoot连接MongoDB操作
  5. python数据拼接: pd.concat
  6. Windows7 IIS7.5 HTTP Error 503 The service is unavailable 另类解决方案
  7. C#获取网上图片的宽高代码
  8. 举例说明TCP/IP
  9. 摘自网络上总结出的一些开源的技术
  10. ios - 带动画圆形旋转的进度条
  11. 如何删除MySQL服务
  12. mysql能够跨平台使用吗_Mysql跨平台(Windows,Linux,Mac)使用与安装
  13. Linux常用命令——insmod命令
  14. python--圆周率的计算
  15. 1米*1米*1米*1米*1米等于什么?
  16. 使用 OpenCV-Python 识别答题卡判卷
  17. FastJson - JSONObject 如何设置成有序?(如:LinkedHashMap)
  18. 解决标题党的计算机算法用户app,今日头条算法工程师:做好推荐必须打击标题党...
  19. 大小写数字转换(大小写数字转换)
  20. Android OpenGL ES 基础原理

热门文章

  1. raspberry pi_使用Raspberry Pi配置业余无线电网关
  2. 拒绝offer的理由_接受拒绝的3大理由
  3. 开源项目面试重要吗_开源是最重要项目的骨干
  4. (50)流式布局—京东移动端首页制作案例
  5. 中文论文万能句型_收藏 | SCI 论文写作的万能句型(二)
  6. react优秀项目案例_关于进行2019年北京市高等学校“实培计划”项目——毕业设计(创业类)项目总结与优秀项目案例征集的通知...
  7. 字体方向 道路标注_自动驾驶环境感知的“见闻色”——3D点云标注
  8. java服务端集成极光消息推送--详细开发步骤
  9. CH2401 送礼物 双向搜索
  10. 51单片机学习笔记(郭天祥版)(3)——引脚讲解、数码管静态显示、中断系统(外部中断,定时器中断)...