上周五一哥们发了条SQL,让我看看,代码如下:

  1. SELECT COUNT(1)
  2. FROM (select m.sheet_id
  3. from cpm_main_sheet_history m, cpm_service_warn_config s
  4. where m.sheet_type_id in
  5. (select t.row_id
  6. from tbl_class_trees t
  7. start with t.row_id = s.sheet_type_id
  8. connect by t.parent_row_id = prior t.row_id)
  9. and m.service_type in
  10. (select tt.row_id
  11. from tbl_class_trees tt
  12. start with tt.row_id = s.business_type_id
  13. connect by tt.parent_row_id = prior tt.row_id)
  14. and m.accept_time >=
  15. TO_CHAR(SYSDATE - time_interval / 24, 'yyyy-mm-dd hh24:mi:ss')
  16. and s.row_id = 'AS170904165251'
  17. and m.no_area in ('0000')) c__
  18. --执行计划
  19. PLAN_TABLE_OUTPUT
  20. Plan hash value: 2710926849
  21. ----------------------------------------------------------------------------------------------------------------------
  22. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  23. ----------------------------------------------------------------------------------------------------------------------
  24. | 0 | SELECT STATEMENT | | 1 | 143 | 96246 (1)| 00:19:15 |
  25. |* 1 | FILTER | | | | | |
  26. | 2 | NESTED LOOPS | | 1681 | 234K| 746 (1)| 00:00:09 |
  27. | 3 | TABLE ACCESS BY INDEX ROWID | CPM_SERVICE_WARN_CONFIG | 1 | 56 | 1 (0)| 00:00:01 |
  28. |* 4 | INDEX UNIQUE SCAN | PK_CONFIG_ROW_ID | 1 | | 0 (0)| 00:00:01 |
  29. | 5 | TABLE ACCESS BY INDEX ROWID | CPM_MAIN_SHEET_HISTORY | 1681 | 142K| 745 (1)| 00:00:09 |
  30. |* 6 | INDEX RANGE SCAN | IDX_CPM_NO_AREA_TIME1 | 449 | | 62 (0)| 00:00:01 |
  31. |* 7 | FILTER | | | | | |
  32. |* 8 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
  33. | 9 | TABLE ACCESS FULL | TBL_CLASS_TREES | 9527 | 493K| 113 (0)| 00:00:02 |
  34. |* 10 | FILTER | | | | | |
  35. |* 11 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
  36. | 12 | TABLE ACCESS FULL | TBL_CLASS_TREES | 9527 | 493K| 113 (0)| 00:00:02 |
  37. ----------------------------------------------------------------------------------------------------------------------
  38. Predicate Information (identified by operation id):
  39. ---------------------------------------------------
  40. 1 - filter( EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "T" WHERE "T"."ROW_ID"=:B1 START WITH "T"."ROW_ID"=:B2
  41. CONNECT BY "T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID") AND EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "TT" WHERE
  42. "TT"."ROW_ID"=:B3 START WITH "TT"."ROW_ID"=:B4 CONNECT BY "TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID"))
  43. 4 - access("S"."ROW_ID"='AS170904165251')
  44. 6 - access("M"."ACCEPT_TIME">=TO_CHAR(SYSDATE@!-"TIME_INTERVAL"/24,'yyyy-mm-dd hh24:mi:ss') AND
  45. "M"."NO_AREA"='0000' AND "M"."ACCEPT_TIME" IS NOT NULL)
  46. filter("M"."NO_AREA"='0000')
  47. 7 - filter("T"."ROW_ID"=:B1)
  48. 8 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
  49. filter("T"."ROW_ID"=:B1)
  50. 10 - filter("TT"."ROW_ID"=:B1)
  51. 11 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
  52. filter("TT"."ROW_ID"=:B1)

SQL优化前:

耗时:20s

count(1)返回: 147条数据

分析执行计划,执行计划中有filter关键字且有3个子级,这种sql是最容易引起性能问题的,所以第一时间是反应是sql有没有走索引,能不能改写。

尝试1:

建索引优化:

  1. TBL_CLASS_TREES表(row_id,parent_row_id)上建索引
  2. 执行计划:
  3. PLAN_TABLE_OUTPUT
  4. Plan hash value: 135779572
  5. ----------------------------------------------------------------------------------------------------------------------
  6. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  7. ----------------------------------------------------------------------------------------------------------------------
  8. | 0 | SELECT STATEMENT | | 1 | 155 | 34147 (1)| 00:06:50 |
  9. |* 1 | FILTER | | | | | |
  10. | 2 | NESTED LOOPS | | 3021 | 457K| 816 (1)| 00:00:10 |
  11. | 3 | TABLE ACCESS BY INDEX ROWID | CPM_SERVICE_WARN_CONFIG | 1 | 62 | 1 (0)| 00:00:01 |
  12. |* 4 | INDEX UNIQUE SCAN | PK_CONFIG_ROW_ID | 1 | | 0 (0)| 00:00:01 |
  13. | 5 | TABLE ACCESS BY INDEX ROWID | CPM_MAIN_SHEET_HISTORY | 3021 | 274K| 815 (1)| 00:00:10 |
  14. |* 6 | INDEX RANGE SCAN | IDX_CPM_NO_AREA_TIME1 | 563 | | 136 (0)| 00:00:02 |
  15. |* 7 | FILTER | | | | | |
  16. |* 8 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
  17. | 9 | INDEX FAST FULL SCAN | IDX_ROW_ID | 9527 | 493K| 20 (0)| 00:00:01 |
  18. |* 10 | FILTER | | | | | |
  19. |* 11 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
  20. | 12 | INDEX FAST FULL SCAN | IDX_ROW_ID | 9527 | 493K| 20 (0)| 00:00:01 |
  21. ----------------------------------------------------------------------------------------------------------------------
  22. Predicate Information (identified by operation id):
  23. ---------------------------------------------------
  24. 1 - filter( EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "T" WHERE "T"."ROW_ID"=:B1 START WITH "T"."ROW_ID"=:B2
  25. CONNECT BY "T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID") AND EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "TT" WHERE
  26. "TT"."ROW_ID"=:B3 START WITH "TT"."ROW_ID"=:B4 CONNECT BY "TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID"))
  27. 4 - access("S"."ROW_ID"='AS170904165251')
  28. 6 - access("M"."ACCEPT_TIME">=TO_CHAR(SYSDATE@!-"TIME_INTERVAL"/24,'yyyy-mm-dd hh24:mi:ss') AND
  29. "M"."NO_AREA"='0000' AND "M"."ACCEPT_TIME" IS NOT NULL)
  30. filter("M"."NO_AREA"='0000')
  31. 7 - filter("T"."ROW_ID"=:B1)
  32. 8 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
  33. filter("T"."ROW_ID"=:B1)
  34. 10 - filter("TT"."ROW_ID"=:B1)
  35. 11 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
  36. filter("TT"."ROW_ID"=:B1)
  37. --效果还是一样慢,此优化失败。

尝试2:

利用with改写sql优化

  1. with t as (select /*+ materialize */ row_id,parent_row_id from tbl_class_trees)
  2. SELECT COUNT(1)
  3. FROM (select m.sheet_id
  4. from cpm_main_sheet_history m,cpm_service_warn_config s
  5. where m.sheet_type_id in
  6. (select t.row_id
  7. from t
  8. start with t.row_id = s.sheet_type_id
  9. connect by t.parent_row_id = prior t.row_id)
  10. and m.service_type in
  11. (select t.row_id
  12. from t
  13. start with t.row_id = s.business_type_id
  14. connect by t.parent_row_id = prior t.row_id)
  15. and m.accept_time >=
  16. TO_CHAR(SYSDATE - time_interval / 24, 'yyyy-mm-dd hh24:mi:ss')
  17. and s.row_id = 'AS170904165251'
  18. and m.no_area in ('0000')) c__
  19. --效果还是一样慢,此优化失败。

再次分析原SQL执行计划:

  1. id=8,id=11的执行计划关键词是:CONNECT BY NO FILTERING WITH SW (UNIQUE)。
  2. 这个为树形查询在11g中的新特性,尝试让sql不使用这个新特性。
  3. 于是使用以下hint/*+ connect_by_filtering */ 进行优化:
  4. SELECT COUNT(1)
  5. FROM (select m.sheet_id
  6. from cpm_main_sheet_history m, cpm_service_warn_config s
  7. where m.sheet_type_id in
  8. (select /*+ connect_by_filtering */ t.row_id
  9. from tbl_class_trees t
  10. start with t.row_id = s.sheet_type_id
  11. connect by t.parent_row_id = prior t.row_id)
  12. and m.service_type in
  13. (select /*+ connect_by_filtering */ tt.row_id
  14. from tbl_class_trees tt
  15. start with tt.row_id = s.business_type_id
  16. connect by tt.parent_row_id = prior tt.row_id)
  17. and m.accept_time >=
  18. TO_CHAR(SYSDATE - time_interval / 24, 'yyyy-mm-dd hh24:mi:ss')
  19. and s.row_id = 'AS170904165251'
  20. and m.no_area in ('0000')) c__
  21. PLAN_TABLE_OUTPUT
  22. Plan hash value: 2824841339
  23. ----------------------------------------------------------------------------------------------------------
  24. | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
  25. ----------------------------------------------------------------------------------------------------------
  26. | 0 | SELECT STATEMENT | | 1 | 246 | 188K (1)| 00:37:47 |
  27. |* 1 | FILTER | | | | | |
  28. | 2 | NESTED LOOPS | | 3021 | 725K| 816 (1)| 00:00:10 |
  29. | 3 | TABLE ACCESS BY INDEX ROWID | CPM_SERVICE_WARN_CONFIG | 1 | 106 | 1 (0)| 00:00:01 |
  30. |* 4 | INDEX UNIQUE SCAN | PK_CONFIG_ROW_ID | 1 | | 0 (0)| 00:00:01 |
  31. | 5 | TABLE ACCESS BY INDEX ROWID | CPM_MAIN_SHEET_HISTORY | 3021 | 413K| 815 (1)| 00:00:10 |
  32. |* 6 | INDEX RANGE SCAN | IDX_CPM_NO_AREA_TIME1 | 563 | | 136 (0)| 00:00:02 |
  33. |* 7 | FILTER | | | | | |
  34. |* 8 | CONNECT BY WITH FILTERING | | | | | |
  35. | 9 | TABLE ACCESS BY INDEX ROWID| TBL_CLASS_TREES | 1 | 107 | 2 (0)| 00:00:01 |
  36. |* 10 | INDEX UNIQUE SCAN | PK_TBL_CLASS_TREESS | 1 | | 1 (0)| 00:00:01 |
  37. |* 11 | HASH JOIN | | | | | |
  38. | 12 | CONNECT BY PUMP | | | | | |
  39. | 13 | TABLE ACCESS FULL | TBL_CLASS_TREES | 6 | 318 | 113 (0)| 00:00:02 |
  40. |* 14 | FILTER | | | | | |
  41. |* 15 | CONNECT BY WITH FILTERING | | | | | |
  42. | 16 | TABLE ACCESS BY INDEX ROWID| TBL_CLASS_TREES | 1 | 107 | 2 (0)| 00:00:01 |
  43. |* 17 | INDEX UNIQUE SCAN | PK_TBL_CLASS_TREESS | 1 | | 1 (0)| 00:00:01 |
  44. |* 18 | HASH JOIN | | | | | |
  45. | 19 | CONNECT BY PUMP | | | | | |
  46. | 20 | TABLE ACCESS FULL | TBL_CLASS_TREES | 6 | 318 | 113 (0)| 00:00:02 |
  47. ----------------------------------------------------------------------------------------------------------
  48. Predicate Information (identified by operation id):
  49. ---------------------------------------------------
  50. 1 - filter( EXISTS (SELECT /*+ CONNECT_BY_FILTERING */ 0 FROM "TBL_CLASS_TREES" "T" WHERE
  51. "T"."ROW_ID"=:B1 START WITH "T"."ROW_ID"=:B2) AND EXISTS (SELECT /*+ CONNECT_BY_FILTERING */ 0
  52. FROM "TBL_CLASS_TREES" "TT" WHERE "TT"."ROW_ID"=:B3 START WITH "TT"."ROW_ID"=:B4))
  53. 4 - access("S"."ROW_ID"='AS170904165251')
  54. 6 - access("M"."ACCEPT_TIME">=TO_CHAR(SYSDATE@!-"TIME_INTERVAL"/24,'yyyy-mm-dd hh24:mi:ss')
  55. AND "M"."NO_AREA"='0000' AND "M"."ACCEPT_TIME" IS NOT NULL)
  56. filter("M"."NO_AREA"='0000')
  57. 7 - filter("T"."ROW_ID"=:B1)
  58. 8 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
  59. 10 - access("T"."ROW_ID"=:B1)
  60. 11 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
  61. 14 - filter("TT"."ROW_ID"=:B1)
  62. 15 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
  63. 17 - access("TT"."ROW_ID"=:B1)
  64. 18 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
  65. --优化后,SQL能在5s返回结果

树形查询SQL优化一例的更多相关文章

  1. 跨服务器查询sql语句样例

    若2个数据库在同一台机器上:insert into DataBase_A..Table1(col1,col2,col3----)select col11,col22,col33-- from Data ...

  2. 跨服务器查询sql语句样例(转)

    若2个数据库在同一台机器上: insert into DataBase_A..Table1(col1,col2,col3----) select col11,col22,col33-- from Da ...

  3. oracle 11g亿级复杂SQL优化一例(数量级性能提升)

    自从16年之后,因为工作原因,项目中就没有再使用oracle了,最近最近支持一个项目,又要开始负责这块事情了.最近在跑性能测试,配置全部调好之后,不少sql还存在性能低下的问题,主要涉及执行计划的不合 ...

  4. 查询SQL优化

    SQL优化的一般步骤 通过show status命令了解各种SQL的执行频率定位执行效率较低的SQL语句,重点select通过explain分析低效率的SQL确定问题并采取相应的优化措施 优化措施 s ...

  5. 反连接NOT EXISTS子查询中有or 谓词连接条件SQL优化一例

    背景 今天在日常数据库检查中,发现一SQL运行时间特别长,于是抓取出来,进行优化. 优化前: 耗时:503s 返回:0 SQL代码 SELECT * FROM MM_PAYABLEMONEY_TD P ...

  6. 1 min 数据查询 SQL 优化

    问题 前几天线上数据库 IOPS 飙升,一直居高不下,最近并没有升级.遂查看数据库正在执行的 SQL 语句,发现有个查询离线设备的语句极其缓慢. 探寻原因 SELECT o.* FROM ( SELE ...

  7. mysql联合查询sql优化

    我们在使用mysql数据库时,经常会使用到mysql的联合查询,联合查询分为内连接和外连接,内连接查询结果是联合的表都存在匹配才会有结果,外连接则根据驱动表是否存在匹配来生成结果集. 这里使用mysq ...

  8. oracle查询SQL优化相当重要

    如果表中的时间字段是索引,那么时间字段不要使用函数,函数会使索引失效. 例如: select * from mytable where trunc(createtime)=trunc(sysdate) ...

  9. Mysql 分页查询sql优化

    先查下数据表的总条数: SELECT COUNT(id) FROM ts_translation_send_address 执行分页界SQL 查看使用时间2.210s SELECT * FROM ts ...

随机推荐

  1. svn报错:privious operation has not finshed;run 'cleanup' if it was interrupted

    在更新svn的过程中,可能中途会取消,取消之后再次更新时可能提示,如下图: 下载sqlite3工具,进入此下载地址:https://www.sqlite.org/download.html 将sqli ...

  2. bzoj 1699: [Usaco2007 Jan]Balanced Lineup排队【st表||线段树】

    要求区间取min和max,可以用st表或线段树维护 st表 #include<iostream> #include<cstdio> using namespace std; c ...

  3. 51nod 1238 最小公倍数之和 V3 【欧拉函数+杜教筛】

    首先题目中给出的代码打错了,少了个等于号,应该是 G=0; for(i=1;i<=N;i++) for(j=1;j<=N;j++) { G = (G + lcm(i,j)) % 10000 ...

  4. 进击的Python【第十五章】:Web前端基础之DOM

    进击的Python[第十五章]:Web前端基础之DOM 简介:文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示 ...

  5. 题解报告:hdu 1171 Big Event in HDU(多重背包)

    Problem Description Nowadays, we all know that Computer College is the biggest department in HDU. Bu ...

  6. C#中如何判断键盘按键和组合键

    好记性不如烂笔头子,现在记录下来,不一定会有很详尽的实例,只写最核心的部分. C# winform的窗体类有KeyPreview属性,可以接收窗体内控件的键盘事件注册.窗体和控件都有KeyDown,K ...

  7. 1270 数组的最大代价 dp

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1270&judgeId=194704 一开始贪心,以为就两种情况, ...

  8. SpringMVC -- 必知必会

    SpringMVC基于模型--视图--控制器(Model-View-Controller,MVC)模式实现,属于SpringFrameWork的后续产品,已经融合在SpringWebFlow里面.它通 ...

  9. java之java.lang.UnsupportedClassVersionError:com/mysql/jdbc/Driver : Unsupported major.minor version 52.0

    问题解释:jdk版本和mysql驱动版本不兼容,比如:jdk1.7与mysql-connector-java-5.xxx兼容,但与mysql-connector-java-6.xxx及以上不兼容

  10. js内置对象总结

    在js里,一切皆为或者皆可以被用作对象.可通过new一个对象或者直接以字面量形式创建变量(如var i="aaa"),所有变量都有对象的性质. 注意:通过字面量创建的对象在调用属性 ...