树形查询SQL优化一例
上周五一哥们发了条SQL,让我看看,代码如下:
SELECT COUNT(1)
FROM (select m.sheet_id
from cpm_main_sheet_history m, cpm_service_warn_config s
where m.sheet_type_id in
(select t.row_id
from tbl_class_trees t
start with t.row_id = s.sheet_type_id
connect by t.parent_row_id = prior t.row_id)
and m.service_type in
(select tt.row_id
from tbl_class_trees tt
start with tt.row_id = s.business_type_id
connect by tt.parent_row_id = prior tt.row_id)
and m.accept_time >=
TO_CHAR(SYSDATE - time_interval / 24, 'yyyy-mm-dd hh24:mi:ss')
and s.row_id = 'AS170904165251'
and m.no_area in ('0000')) c__
--执行计划
PLAN_TABLE_OUTPUT
Plan hash value: 2710926849
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 143 | 96246 (1)| 00:19:15 |
|* 1 | FILTER | | | | | |
| 2 | NESTED LOOPS | | 1681 | 234K| 746 (1)| 00:00:09 |
| 3 | TABLE ACCESS BY INDEX ROWID | CPM_SERVICE_WARN_CONFIG | 1 | 56 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_CONFIG_ROW_ID | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID | CPM_MAIN_SHEET_HISTORY | 1681 | 142K| 745 (1)| 00:00:09 |
|* 6 | INDEX RANGE SCAN | IDX_CPM_NO_AREA_TIME1 | 449 | | 62 (0)| 00:00:01 |
|* 7 | FILTER | | | | | |
|* 8 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
| 9 | TABLE ACCESS FULL | TBL_CLASS_TREES | 9527 | 493K| 113 (0)| 00:00:02 |
|* 10 | FILTER | | | | | |
|* 11 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
| 12 | TABLE ACCESS FULL | TBL_CLASS_TREES | 9527 | 493K| 113 (0)| 00:00:02 |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "T" WHERE "T"."ROW_ID"=:B1 START WITH "T"."ROW_ID"=:B2
CONNECT BY "T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID") AND EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "TT" WHERE
"TT"."ROW_ID"=:B3 START WITH "TT"."ROW_ID"=:B4 CONNECT BY "TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID"))
4 - access("S"."ROW_ID"='AS170904165251')
6 - access("M"."ACCEPT_TIME">=TO_CHAR(SYSDATE@!-"TIME_INTERVAL"/24,'yyyy-mm-dd hh24:mi:ss') AND
"M"."NO_AREA"='0000' AND "M"."ACCEPT_TIME" IS NOT NULL)
filter("M"."NO_AREA"='0000')
7 - filter("T"."ROW_ID"=:B1)
8 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
filter("T"."ROW_ID"=:B1)
10 - filter("TT"."ROW_ID"=:B1)
11 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
filter("TT"."ROW_ID"=:B1)
SQL优化前:
耗时:20s
count(1)返回: 147条数据
分析执行计划,执行计划中有filter关键字且有3个子级,这种sql是最容易引起性能问题的,所以第一时间是反应是sql有没有走索引,能不能改写。
尝试1:
建索引优化:
在TBL_CLASS_TREES表(row_id,parent_row_id)上建索引
执行计划:
PLAN_TABLE_OUTPUT
Plan hash value: 135779572
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 155 | 34147 (1)| 00:06:50 |
|* 1 | FILTER | | | | | |
| 2 | NESTED LOOPS | | 3021 | 457K| 816 (1)| 00:00:10 |
| 3 | TABLE ACCESS BY INDEX ROWID | CPM_SERVICE_WARN_CONFIG | 1 | 62 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_CONFIG_ROW_ID | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID | CPM_MAIN_SHEET_HISTORY | 3021 | 274K| 815 (1)| 00:00:10 |
|* 6 | INDEX RANGE SCAN | IDX_CPM_NO_AREA_TIME1 | 563 | | 136 (0)| 00:00:02 |
|* 7 | FILTER | | | | | |
|* 8 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
| 9 | INDEX FAST FULL SCAN | IDX_ROW_ID | 9527 | 493K| 20 (0)| 00:00:01 |
|* 10 | FILTER | | | | | |
|* 11 | CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | |
| 12 | INDEX FAST FULL SCAN | IDX_ROW_ID | 9527 | 493K| 20 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "T" WHERE "T"."ROW_ID"=:B1 START WITH "T"."ROW_ID"=:B2
CONNECT BY "T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID") AND EXISTS (SELECT 0 FROM "TBL_CLASS_TREES" "TT" WHERE
"TT"."ROW_ID"=:B3 START WITH "TT"."ROW_ID"=:B4 CONNECT BY "TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID"))
4 - access("S"."ROW_ID"='AS170904165251')
6 - access("M"."ACCEPT_TIME">=TO_CHAR(SYSDATE@!-"TIME_INTERVAL"/24,'yyyy-mm-dd hh24:mi:ss') AND
"M"."NO_AREA"='0000' AND "M"."ACCEPT_TIME" IS NOT NULL)
filter("M"."NO_AREA"='0000')
7 - filter("T"."ROW_ID"=:B1)
8 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
filter("T"."ROW_ID"=:B1)
10 - filter("TT"."ROW_ID"=:B1)
11 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
filter("TT"."ROW_ID"=:B1)
--效果还是一样慢,此优化失败。
尝试2:
利用with改写sql优化
with t as (select /*+ materialize */ row_id,parent_row_id from tbl_class_trees)
SELECT COUNT(1)
FROM (select m.sheet_id
from cpm_main_sheet_history m,cpm_service_warn_config s
where m.sheet_type_id in
(select t.row_id
from t
start with t.row_id = s.sheet_type_id
connect by t.parent_row_id = prior t.row_id)
and m.service_type in
(select t.row_id
from t
start with t.row_id = s.business_type_id
connect by t.parent_row_id = prior t.row_id)
and m.accept_time >=
TO_CHAR(SYSDATE - time_interval / 24, 'yyyy-mm-dd hh24:mi:ss')
and s.row_id = 'AS170904165251'
and m.no_area in ('0000')) c__
--效果还是一样慢,此优化失败。
再次分析原SQL执行计划:
id=8,id=11的执行计划关键词是:CONNECT BY NO FILTERING WITH SW (UNIQUE)。
这个为树形查询在11g中的新特性,尝试让sql不使用这个新特性。
于是使用以下hint:/*+ connect_by_filtering */ 进行优化:
SELECT COUNT(1)
FROM (select m.sheet_id
from cpm_main_sheet_history m, cpm_service_warn_config s
where m.sheet_type_id in
(select /*+ connect_by_filtering */ t.row_id
from tbl_class_trees t
start with t.row_id = s.sheet_type_id
connect by t.parent_row_id = prior t.row_id)
and m.service_type in
(select /*+ connect_by_filtering */ tt.row_id
from tbl_class_trees tt
start with tt.row_id = s.business_type_id
connect by tt.parent_row_id = prior tt.row_id)
and m.accept_time >=
TO_CHAR(SYSDATE - time_interval / 24, 'yyyy-mm-dd hh24:mi:ss')
and s.row_id = 'AS170904165251'
and m.no_area in ('0000')) c__
PLAN_TABLE_OUTPUT
Plan hash value: 2824841339
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 246 | 188K (1)| 00:37:47 |
|* 1 | FILTER | | | | | |
| 2 | NESTED LOOPS | | 3021 | 725K| 816 (1)| 00:00:10 |
| 3 | TABLE ACCESS BY INDEX ROWID | CPM_SERVICE_WARN_CONFIG | 1 | 106 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_CONFIG_ROW_ID | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID | CPM_MAIN_SHEET_HISTORY | 3021 | 413K| 815 (1)| 00:00:10 |
|* 6 | INDEX RANGE SCAN | IDX_CPM_NO_AREA_TIME1 | 563 | | 136 (0)| 00:00:02 |
|* 7 | FILTER | | | | | |
|* 8 | CONNECT BY WITH FILTERING | | | | | |
| 9 | TABLE ACCESS BY INDEX ROWID| TBL_CLASS_TREES | 1 | 107 | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_TBL_CLASS_TREESS | 1 | | 1 (0)| 00:00:01 |
|* 11 | HASH JOIN | | | | | |
| 12 | CONNECT BY PUMP | | | | | |
| 13 | TABLE ACCESS FULL | TBL_CLASS_TREES | 6 | 318 | 113 (0)| 00:00:02 |
|* 14 | FILTER | | | | | |
|* 15 | CONNECT BY WITH FILTERING | | | | | |
| 16 | TABLE ACCESS BY INDEX ROWID| TBL_CLASS_TREES | 1 | 107 | 2 (0)| 00:00:01 |
|* 17 | INDEX UNIQUE SCAN | PK_TBL_CLASS_TREESS | 1 | | 1 (0)| 00:00:01 |
|* 18 | HASH JOIN | | | | | |
| 19 | CONNECT BY PUMP | | | | | |
| 20 | TABLE ACCESS FULL | TBL_CLASS_TREES | 6 | 318 | 113 (0)| 00:00:02 |
----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT /*+ CONNECT_BY_FILTERING */ 0 FROM "TBL_CLASS_TREES" "T" WHERE
"T"."ROW_ID"=:B1 START WITH "T"."ROW_ID"=:B2) AND EXISTS (SELECT /*+ CONNECT_BY_FILTERING */ 0
FROM "TBL_CLASS_TREES" "TT" WHERE "TT"."ROW_ID"=:B3 START WITH "TT"."ROW_ID"=:B4))
4 - access("S"."ROW_ID"='AS170904165251')
6 - access("M"."ACCEPT_TIME">=TO_CHAR(SYSDATE@!-"TIME_INTERVAL"/24,'yyyy-mm-dd hh24:mi:ss')
AND "M"."NO_AREA"='0000' AND "M"."ACCEPT_TIME" IS NOT NULL)
filter("M"."NO_AREA"='0000')
7 - filter("T"."ROW_ID"=:B1)
8 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
10 - access("T"."ROW_ID"=:B1)
11 - access("T"."PARENT_ROW_ID"=PRIOR "T"."ROW_ID")
14 - filter("TT"."ROW_ID"=:B1)
15 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
17 - access("TT"."ROW_ID"=:B1)
18 - access("TT"."PARENT_ROW_ID"=PRIOR "TT"."ROW_ID")
--优化后,SQL能在5s返回结果
树形查询SQL优化一例的更多相关文章
- 跨服务器查询sql语句样例
若2个数据库在同一台机器上:insert into DataBase_A..Table1(col1,col2,col3----)select col11,col22,col33-- from Data ...
- 跨服务器查询sql语句样例(转)
若2个数据库在同一台机器上: insert into DataBase_A..Table1(col1,col2,col3----) select col11,col22,col33-- from Da ...
- oracle 11g亿级复杂SQL优化一例(数量级性能提升)
自从16年之后,因为工作原因,项目中就没有再使用oracle了,最近最近支持一个项目,又要开始负责这块事情了.最近在跑性能测试,配置全部调好之后,不少sql还存在性能低下的问题,主要涉及执行计划的不合 ...
- 查询SQL优化
SQL优化的一般步骤 通过show status命令了解各种SQL的执行频率定位执行效率较低的SQL语句,重点select通过explain分析低效率的SQL确定问题并采取相应的优化措施 优化措施 s ...
- 反连接NOT EXISTS子查询中有or 谓词连接条件SQL优化一例
背景 今天在日常数据库检查中,发现一SQL运行时间特别长,于是抓取出来,进行优化. 优化前: 耗时:503s 返回:0 SQL代码 SELECT * FROM MM_PAYABLEMONEY_TD P ...
- 1 min 数据查询 SQL 优化
问题 前几天线上数据库 IOPS 飙升,一直居高不下,最近并没有升级.遂查看数据库正在执行的 SQL 语句,发现有个查询离线设备的语句极其缓慢. 探寻原因 SELECT o.* FROM ( SELE ...
- mysql联合查询sql优化
我们在使用mysql数据库时,经常会使用到mysql的联合查询,联合查询分为内连接和外连接,内连接查询结果是联合的表都存在匹配才会有结果,外连接则根据驱动表是否存在匹配来生成结果集. 这里使用mysq ...
- oracle查询SQL优化相当重要
如果表中的时间字段是索引,那么时间字段不要使用函数,函数会使索引失效. 例如: select * from mytable where trunc(createtime)=trunc(sysdate) ...
- Mysql 分页查询sql优化
先查下数据表的总条数: SELECT COUNT(id) FROM ts_translation_send_address 执行分页界SQL 查看使用时间2.210s SELECT * FROM ts ...
随机推荐
- window切换Java版本原因
查找Path环境变量的变量指向的目录,有一个Oracle目录存放着几个 java,javac等可执行文件,删除这个路径或文件就可以执行你指定的JavaHome目录拉 详情参考: https://blo ...
- [App Store Connect帮助]七、在 App Store 上发行(2.4)设定价格与销售范围:安排价格调整
如果您拥有<付费应用程序协议>,则可以为您的 App 安排随时间推移的价格调整.您可以安排具有明确开始日期和结束日期的定价调整,以及没有结束日期的永久性定价调整.例如,您可以设置一个为期 ...
- 一个 Java 对象到底有多大?
阅读本文大概需要 2.8 分钟. 出处:http://u6.gg/swLPg 编写 Java 代码的时候,大多数情况下,我们很少关注一个 Java 对象究竟有多大(占据多少内存),更多的是关注业务与逻 ...
- 利用动态扫描和定时器1在数码管上显示出从765432开始以1/10秒的速度往下递减 直至765398并保持此数,与此同时利用定时器0以500MS速度进行流水灯从上至下移动 ,当数码管上数减到停止时,实验板上流水灯出停止然后全部开始闪烁,3秒后(用 T0定时)流水灯全部关闭,数码管上显示出“HELLO”,到此保持住
#include <reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigne ...
- python 匿名函数的使用(并没有那么简单)
以下为几种匿名函数的使用方式:x=[(lambda x:x**2)(x) for x in range(10)]print(x)y=[x**2 for x in range(10)]print(y)i ...
- 【react native】有关入坑3个月RN的心路历程
由于一些原因,笔者最近变更到了RN的团队,回归到了hybrid app的开发的圈子中,固然是有蛮多新鲜感和新机遇的,不过遥想起以前在hybrid中各种view之前跳转的头疼等各种问题,笔者怀着忐忑的心 ...
- [CF Round #278] Tourists
给定一个n个点m条边的无向图,求图上的两点的所有的简单路径之间的最小边. 蓝链 $ n,m,q \leq 100000, w_i \leq 10 ^7$ Solution 考虑建立用缩点双来建立广义圆 ...
- LoadRunner_11破解教程完整版
2017.12.17更正 qtm的LR11,如果是win10版本的电脑而且ie浏览器是11以上的请到loadrunner官网下载社区免费版,支持google,firefox,edge,ie11四大浏览 ...
- C# 基础知识和VS2010的小技巧总汇
看了一些基础视频,才发现自己的基础比较薄弱,有很多基础知识都不知道.这里总汇一些基础知识. 1: foreach不仅可以作用于list类的索引集合,还可以遍历dictionary类,这一点比for更简 ...
- lock to deteck in oracle
0,5,10 0-23 * * * /home/oracle/utility/blocker/detect_blocker.sh db 120 > /home/oracle/utility/tr ...