帮盖尔优化SQL-----子查询优化的经典案例
上周五要下班的时候,盖尔发来一个SQL
select tpc.policy_id,tcm.policy_code,tpf.organ_id,to_char(tpf.insert_time, 'YYYY-MM-DD') As insert_time,tpc.change_id,d.policy_code,e.company_name,f.real_name,tpf.fee_type,sum(tpf.pay_balance) as pay_balance,c.actual_type,tpc.notice_code,d.policy_type,g.mode_name as pay_modefrom t_policy_change tpc,t_contract_master tcm,t_policy_fee tpf,t_fee_type c,t_contract_master d,t_company_customer e,t_customer f,t_pay_mode gwhere tpc.change_id = tpf.change_idand tpf.policy_id = d.policy_idand tcm.policy_id = tpc.policy_idand tpf.receiv_status = 1 and tpf.fee_status = 1and tpf.payment_id is nulland tpf.fee_type = c.type_idand tpf.pay_mode = g.mode_idand d.company_id = e.company_id(+)and d.applicant_id = f.customer_id(+)and tpf.organ_id in(select organ_idfrom t_company_organstart with organ_id = '101'connect by prior organ_id = parent_id)group by tpc.policy_id,tpc.change_id,tpf.fee_type,to_char(tpf.insert_time, 'YYYY-MM-DD'),c.actual_type,d.policy_code,g.mode_name,e.company_name,f.real_name,tpc.notice_code,d.policy_type,tpf.organ_id,tcm.policy_codeorder by change_id, fee_typeSQL> select * from table(dbms_xplan.display);PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 45962 | 11M| | 45650 (0)|
| 1 | SORT GROUP BY | | 45962 | 11M| 23M| 45650 (0)|
|* 2 | HASH JOIN | | 45962 | 11M| | 43908 (0)|
| 3 | INDEX FULL SCAN | T_FEE_TYPE_IDX_003 | 106 | 636 | | 1 (0)|
| 4 | NESTED LOOPS OUTER | | 45962 | 11M| | 43906 (0)|
|* 5 | HASH JOIN | | 45962 | 7271K| 6824K| 43905 (0)|
| 6 | NESTED LOOPS | | 45961 | 6283K| | 42312 (0)|
|* 7 | HASH JOIN SEMI | | 45961 | 5655K| 50M| 33120 (1)|
|* 8 | HASH JOIN OUTER | | 400K| 45M| 44M| 32315 (1)|
|* 9 | HASH JOIN | | 400K| 39M| 27M| 26943 (0)|
|* 10 | HASH JOIN | | 400K| 23M| | 16111 (0)|
| 11 | TABLE ACCESS FULL | T_PAY_MODE | 25 | 525 | | 2 (0)|
|* 12 | TABLE ACCESS FULL | T_POLICY_FEE | 400K| 15M| | 16107 (0)|
| 13 | TABLE ACCESS FULL | T_CONTRACT_MASTER | 1136K| 46M| | 9437 (0)|
| 14 | VIEW | index_join_007 | 2028K| 30M| | |
|* 15 | HASH JOIN | | 400K| 45M| 44M| 32315 (1)|
| 16 | INDEX FAST FULL SCAN | PK_T_CUSTOMER | 2028K| 30M| | 548 (0)|
| 17 | INDEX FAST FULL SCAN | IDX_CUSTOMER__BIR_REAL_GEN | 2028K| 30M| | 548 (0)|
| 18 | VIEW | VW_NSO_1 | 7 | 42 | | |
|* 19 | CONNECT BY WITH FILTERING | | | | | |
| 20 | NESTED LOOPS | | | | | |
|* 21 | INDEX UNIQUE SCAN | PK_T_COMPANY_ORGAN | 1 | 6 | | |
| 22 | TABLE ACCESS BY USER ROWID| T_COMPANY_ORGAN | | | | |
| 23 | NESTED LOOPS | | | | | |
| 24 | BUFFER SORT | | 7 | 70 | | |
| 25 | CONNECT BY PUMP | | | | | |
|* 26 | INDEX RANGE SCAN | T_COMPANY_ORGAN_IDX_002 | 7 | 70 | | 1 (0)|
| 27 | TABLE ACCESS BY INDEX ROWID | T_POLICY_CHANGE | 1 | 14 | | 2 (50)|
|* 28 | INDEX UNIQUE SCAN | PK_T_POLICY_CHANGE | 1 | | | 1 (0)|
| 29 | INDEX FAST FULL SCAN | IDX1_ACCEPT_DATE | 1136K| 23M| | 899 (0)|
| 30 | TABLE ACCESS BY INDEX ROWID | T_COMPANY_CUSTOMER | 1 | 90 | | 2 (50)|
|* 31 | INDEX UNIQUE SCAN | PK_T_COMPANY_CUSTOMER | 1 | | | |
----------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - access("TPF"."FEE_TYPE"="C"."TYPE_ID")5 - access("TCM"."POLICY_ID"="TPC"."POLICY_ID")7 - access("TPF"."ORGAN_ID"="VW_NSO_1"."$nso_col_1")8 - access("D"."APPLICANT_ID"="F"."CUSTOMER_ID"(+))9 - access("TPF"."POLICY_ID"="D"."POLICY_ID")10 - access("TPF"."PAY_MODE"="G"."MODE_ID")12 - filter("TPF"."CHANGE_ID" IS NOT NULL AND TO_NUMBER("TPF"."RECEIV_STATUS")=1 AND "TPF"."FEE_STATUS"=1 AND"TPF"."PAYMENT_ID" IS NULL)15 - access("indexjoin_alias_012".ROWID="indexjoin_alias_011".ROWID)19 - filter("T_COMPANY_ORGAN"."ORGAN_ID"='101')21 - access("T_COMPANY_ORGAN"."ORGAN_ID"='101')26 - access("T_COMPANY_ORGAN"."PARENT_ID"=NULL)28 - access("TPC"."CHANGE_ID"="TPF"."CHANGE_ID")31 - access("D"."COMPANY_ID"="E"."COMPANY_ID"(+))55 rows selectedStatistics
----------------------------------------------------------21 recursive calls0 db block gets125082 consistent gets21149 physical reads0 redo size2448 bytes sent via SQL*Net to client656 bytes received via SQL*Net from client2 SQL*Net roundtrips to/from client4 sorts (memory)0 sorts (disk)11 rows processed
这个SQL要21秒才能跑完,逻辑读12W左右,问我能不能优化。优化这个SQL我只花了1分钟左右的时间,因为太简单了
你们看这个SQL是典型的JOIN,对付这种SQL肯定要让表走索引,但是从执行计划上看有个1千万行的表T_CONTRACT_MASTER走的是全表扫描,
T_POLICY_FEE 这个400W行的表也是走全表扫描,那么它不慢才怪呢,然后SQL的过滤条件有个 in 子查询
(select
organ_id
from t_company_organ
start with organ_id = '101'
connect by prior organ_id = parent_id)
从执行计划上看,CBO对这儿子查询进行了unnest,因为通常情况下CBO认为子查询被unnest之后性能好于filter
于是我让盖尔查询 子查询返回多少行
select organ_id
from t_company_organ
start with organ_id = '101'
connect by prior organ_id = parent_id ---盖尔说它返回1行
对于子查询,如果它返回数据很少(这里返回1行),那么可以让它走filter, 而且filter基本上是在SQL最后去阶段执行,这样t_policy_fee就可以走索引了
所以我给这个子查询加了个HINT,禁止子查询扩展
select tpc.policy_id,tcm.policy_code,tpf.organ_id,to_char(tpf.insert_time, 'YYYY-MM-DD') As insert_time,tpc.change_id,d.policy_code,e.company_name,f.real_name,tpf.fee_type,sum(tpf.pay_balance) as pay_balance,c.actual_type,tpc.notice_code,d.policy_type,g.mode_name as pay_modefrom t_policy_change tpc,t_contract_master tcm,t_policy_fee tpf,t_fee_type c,t_contract_master d,t_company_customer e,t_customer f,t_pay_mode gwhere tpc.change_id = tpf.change_idand tpf.policy_id = d.policy_idand tcm.policy_id = tpc.policy_idand tpf.receiv_status = '1' ---这里原来没引号,是开发那SB搞忘了写'',我让盖尔添加上了,不添加上就没法用索引and tpf.fee_status = 1and tpf.payment_id is nulland tpf.fee_type = c.type_idand tpf.pay_mode = g.mode_idand d.company_id = e.company_id(+)and d.applicant_id = f.customer_id(+)and tpf.organ_id in(select /*+ no_unnest */ --此处的HINT后加的organ_idfrom t_company_organstart with organ_id = '101'connect by prior organ_id = parent_id)group by tpc.policy_id,tpc.change_id,tpf.fee_type,to_char(tpf.insert_time, 'YYYY-MM-DD'),c.actual_type,d.policy_code,g.mode_name,e.company_name,f.real_name,tpc.notice_code,d.policy_type,tpf.organ_id,tcm.policy_codeorder by change_id, fee_typeSQL> select * from table(dbms_xplan.display);PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20026 | 4928K| | 68615 (30)|
| 1 | SORT GROUP BY | | 20026 | 4928K| 10M| 28563 (0)|
|* 2 | FILTER | | | | | |
| 3 | NESTED LOOPS | | 20026 | 4928K| | 27812 (0)|
| 4 | NESTED LOOPS | | 20026 | 4498K| | 23807 (0)|
| 5 | NESTED LOOPS OUTER | | 20026 | 4224K| | 19802 (0)|
| 6 | NESTED LOOPS OUTER | | 20026 | 3911K| | 15797 (0)|
| 7 | NESTED LOOPS | | 20026 | 2151K| | 15796 (0)|
|* 8 | HASH JOIN | | 20026 | 1310K| | 11791 (0)|
| 9 | INDEX FULL SCAN | T_FEE_TYPE_IDX_003 | 106 | 636 | | 1 (0)|
|* 10 | HASH JOIN | | 20026 | 1192K| | 11789 (0)|
| 11 | TABLE ACCESS FULL | T_PAY_MODE | 25 | 525 | | 2 (0)|
|* 12 | TABLE ACCESS BY INDEX ROWID| T_POLICY_FEE | 20026 | 782K| | 11786 (0)|
|* 13 | INDEX RANGE SCAN | IDX_POLICY_FEE__RECEIV_STATUS | 1243K| | | 10188 (0)|
| 14 | TABLE ACCESS BY INDEX ROWID | T_CONTRACT_MASTER | 1 | 43 | | 2 (50)|
|* 15 | INDEX UNIQUE SCAN | PK_T_CONTRACT_MASTER | 1 | | | 1 (0)|
| 16 | TABLE ACCESS BY INDEX ROWID | T_COMPANY_CUSTOMER | 1 | 90 | | 2 (50)|
|* 17 | INDEX UNIQUE SCAN | PK_T_COMPANY_CUSTOMER | 1 | | | |
| 18 | TABLE ACCESS BY INDEX ROWID | T_CUSTOMER | 1 | 16 | | 2 (50)|
|* 19 | INDEX UNIQUE SCAN | PK_T_CUSTOMER | 1 | | | 1 (0)|
| 20 | TABLE ACCESS BY INDEX ROWID | T_POLICY_CHANGE | 1 | 14 | | 2 (50)|
|* 21 | INDEX UNIQUE SCAN | PK_T_POLICY_CHANGE | 1 | | | 1 (0)|
| 22 | TABLE ACCESS BY INDEX ROWID | T_CONTRACT_MASTER | 1 | 22 | | 2 (50)|
|* 23 | INDEX UNIQUE SCAN | PK_T_CONTRACT_MASTER | 1 | | | 1 (0)|
|* 24 | FILTER | | | | | |
|* 25 | CONNECT BY WITH FILTERING | | | | | |
| 26 | NESTED LOOPS | | | | | |
|* 27 | INDEX UNIQUE SCAN | PK_T_COMPANY_ORGAN | 1 | 6 | | |
| 28 | TABLE ACCESS BY USER ROWID | T_COMPANY_ORGAN | | | | |
| 29 | NESTED LOOPS | | | | | |
| 30 | BUFFER SORT | | 7 | 70 | | |
| 31 | CONNECT BY PUMP | | | | | |
|* 32 | INDEX RANGE SCAN | T_COMPANY_ORGAN_IDX_002 | 7 | 70 | | 1 (0)|
--------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
---------------------------------------------------2 - filter( EXISTS (SELECT /*+ NO_UNNEST */ 0 FROM "T_COMPANY_ORGAN" "T_COMPANY_ORGAN" WHERE"T_COMPANY_ORGAN"."PARENT_ID"=NULL AND ("T_COMPANY_ORGAN"."ORGAN_ID"=:B1)))8 - access("SYS_ALIAS_1"."FEE_TYPE"="C"."TYPE_ID")10 - access("SYS_ALIAS_1"."PAY_MODE"="G"."MODE_ID")12 - filter("SYS_ALIAS_1"."CHANGE_ID" IS NOT NULL AND "SYS_ALIAS_1"."FEE_STATUS"=1 AND "SYS_ALIAS_1"."PAYMENT_ID"IS NULL)13 - access("SYS_ALIAS_1"."RECEIV_STATUS"='1')15 - access("SYS_ALIAS_1"."POLICY_ID"="D"."POLICY_ID")17 - access("D"."COMPANY_ID"="E"."COMPANY_ID"(+))19 - access("D"."APPLICANT_ID"="F"."CUSTOMER_ID"(+))21 - access("TPC"."CHANGE_ID"="SYS_ALIAS_1"."CHANGE_ID")23 - access("TCM"."POLICY_ID"="TPC"."POLICY_ID")24 - filter("T_COMPANY_ORGAN"."ORGAN_ID"=:B1)25 - filter("T_COMPANY_ORGAN"."ORGAN_ID"='101')27 - access("T_COMPANY_ORGAN"."ORGAN_ID"='101')32 - access("T_COMPANY_ORGAN"."PARENT_ID"=NULL)58 rows selected.Statistics
----------------------------------------------------------0 recursive calls0 db block gets2817 consistent gets0 physical reads0 redo size2268 bytes sent via SQL*Net to client656 bytes received via SQL*Net from client2 SQL*Net roundtrips to/from client40 sorts (memory)0 sorts (disk)9 rows processed
最终这个SQL能在1秒以内跑完,逻辑读下降到2817 ,到此我就没继续优化了,这个时候停止优化吧,别的了强迫优化症
这个优化案例很简单,我都不好意思贴在博客上,通过这个文章你要学到的就是,如果子查询返回数据很少,那么不妨让它走filter
转载于:https://www.cnblogs.com/hehe520/archive/2011/11/29/6330557.html
帮盖尔优化SQL-----子查询优化的经典案例相关推荐
- Mysql 关联查询的优化 及 子查询优化
Mysql 关联查询的优化 left join ①EXPLAIN SELECT * FROM class LEFT JOIN book ON class.card = book.card; ②如何优化 ...
- 【推荐】 RAC 性能优化全攻略与经典案例剖析
ORACLE RAC凭借其卓越的容错能力和可扩展性以及对应用透明的切换能力引领了数据库高可用架构的潮流,但在实际的生产环境中,出现的性能问题非常多,对数据库的稳定性产生很大的影响,有一些甚至影响到了业 ...
- MySQL性能优化:SQL慢查询优化,索引优化,表优化
1. MySQL优化概述 MySQL 优化是一个综合性的技术,在优化上存在着一个调优金字塔的说法,如下: 很明显从图上可以看出,越往上走,难度越来越高,收益却是越来越小的.比如硬件和 OS 调优,需要 ...
- 8、查询优化-关联查询优化-子查询优化-Order by 关键字优化-Group by 关键字优化-双路排序和单路排序
8.查询优化 8.1.准备数据 8.1.1.建表 CREATE TABLE `dept` (`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,`deptName` VAR ...
- SQL优化实战经典案例分析
前言 大家好,我是黎杜,今天和大家聊聊SQL优化的场景. SQL调优这块呢,大厂面试必问的.最近金九银十嘛,所以整理了SQL的调优思路,并且附几个经典案例分析. 1.慢SQL优化思路. 慢查询日志记录 ...
- 【SQL查询系列】子查询经典案例
文章目录 前言 数据库 查询案例 1. 查询工资最低的员工信息: last_name, salary 2. 查询平均工资最低的部门信息 3. 查询平均工资最低的部门信息和该部门的平均工资 4. 查询平 ...
- 干货!常见的SQL面试题:经典50例!
来自:CSDN,作者:sh_c_2450957609 链接:https://blog.csdn.net/u010565545/article/details/100785261 SQL在数据分析中举足 ...
- MySQL调优之关联查询、子查询优化
我们准备如下两个表,并插入数据. #分类 CREATE TABLE IF NOT EXISTS `type` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREME ...
- MySQL优化器_MySQL查询优化器
MySQL优化器 MySQL架构图 讲到MySQL,就绕不开他的架构图.MySQL是一个经典的C/S架构.服务器这边分两层:第一层是Server层,第二层是存储引擎.Server层处理主要的业务操作流 ...
最新文章
- 什么样的域名利于网站SEO优化?
- 微软CEO鲍尔默力推HTML5:称其为平台的粘合剂
- 7.2 DOM方法(以动态方式实时创建标记,实质在改变DOM节点树)
- php子类选择器代码,php – 可变产品选择器:获取实时选定值
- windows内存结构概述
- mediawiki 搭建
- 981. 基于时间的键值存储
- 百度关键词抓取工具_阿里巴巴国际站运营关键词抓取工具
- c语言设计二级考试程序修改题,全国计算机c语言二级考试试题
- 1500个常用计算机单词
- Twaver-HTML5基础学习(3)基本数据元素(Data)其他功能函数以及组Group
- android开启wifi热点命令,Win7共享WIFI热点让Android手机上网
- Android 、AndroidQ 、小米、 oppo等【后台启动界面】问题 解决方案
- 关于博文的禁止评论和允许评论
- oracle导入blob出错,oracle导出blob,clob出错的问题
- 服务器地址错误如何修复,ip地址错误怎么办
- 人家不卡学历,是自己真的没能力
- 【JAVA面试题】java面试题100道详解
- 6to4隧道实验配置
- 华为防火墙配置流量根据链路权重负载分担
热门文章
- linux下错误的捕获:errno、perror和strerror的使用
- android Android项目构建过程
- (WebKit) ViewPort + Backing Store + Page Content
- Python之PIL库
- Python的类Class中__init__函数和self
- 安装使用Frida在Android上进行hook
- 使用apache的HttpGet\HttpPost获取返回内容编码问题
- Exceptions
- [NOI2001]炮兵阵地
- ActiveMQ 实现消息接收发送