导读 | 在 DBA 所优化的数据库环境中,绝大多数性能问题其实是由于 SQL 编写不当导致的。SQL 的世界无奇不有,今天我们一起见识一条让你绝对想吐血的杀手SQL。 |
某保险客户,etl 耗时数个小时,我们做了sql report发现压力主要在其中一个sql上。
单次执行时间:5788(秒)
单次逻辑读:10亿(块)
单次返回行数:21万(行)
我们首先看SQL语句,因为比较长,此处只节选部分的
查看其执行计划:
我们主要关注一下从7到16行:发现存在两次全表扫描。中间做了一次filter。
多年的经验告诉我,两个全表扫组成的Filter ,问题很严重, 因为涉及数据逐条处理。 而这个执行计划里,被驱动表还是全表扫。
Not In/In 操作有时候的确会产生 Filter操作,在11g之前的版本,要把not in 语句转换成反连接,not in条件的列必须有Not null 属性,或者语句中带入了not null的限制,否则只能采用Filter,逐条过滤.
我们举例说明一下:
SQL1:CREATE TABLE T_OBJ AS SELECT OBJECT_ID,OWNER,OBJECT_NAME,OBJECT_TYPE FROM DBA_OBJECTS WHERE OWNER != ‘SEROL’; SQL 2:CREATE TABLET_TABLE AS SELECT OWNER,TABLE_NAME FROM DBA_TABLES WHERE OWNER!=’SEROL’;查看T_OBJ的属性:
发现有在三列上都没有not null的限制。
我们此时伪装成10G的优化器。
SQL> alter session set optimizer_features_enable=”10.2.0.5″;
执行以下SQL:
SQL> set autotracetrace exp
SQL> SELECT * FROM T_TABLE WHERE TABLE_NAME NOT IN(SELECT OBJECT_NAME FROM T_OBJ);
此时查看执行计划,我们发现走的是filter:
但在11g版本中,优化器可以自动把Not in操作从昂贵的Filter转换成Null-Aware-Anti-Join。
若加个Not null 条件或者栏位属性设为not null
SQL> alter table T_OBJ modify(OBJECT_NAME NOT NULL);
再次执行相同语句:
SQL> SELECT * FROM T_TABLE WHERE TABLE_NAME
NOT IN(SELECT OBJECT_NAME FROM T_OBJ
WHEREOBJECT_NAME IS NOT NULL);
再次查看执行计划:
此时我们发现,在执行计划中,走了hash join anti.
并且,在11g里面,允许not in列没有not null 限制也可以转换Anti-Join.
SQL> alter session set optimizer_features_enable=”11.2.0.4″;
SQL> alter table T_OBJ modify(OBJECT_NAME NULL);
SQ> SELECT * FROM T_TABLE WHERE TABLE_NAME
NOT IN (SELECTOBJECT_NAMEFROM T_OBJ);
查看执行计划:
我们看到,此时在没有非空限制的情况下,也走了hash join anti.
这个特性, 可通过优化器参数控制。
SQL>alter session set “_optimizer_null_aware_antijoin”=FALSE;
再次执行以上语句并查看执行计划:
SQL> SELECT * FROM T_TABLE WHERE TABLE_NAME
NOT IN (SELECTOBJECT_NAMEFROM T_OBJ);
发现仍然走的是hash join anti.
经过验证,不是这个参数设置问题
Not in 的逻辑,就是结果集之间的互斥,其实有多种改写的方式,比如:
— Not exists
— Outer Join + is null
— Minus
not in与以上三种写法的区别是:not in 是会排斥空值。
我们尝试改写。
接下来正当你以为会发生奇迹的时候,语句报错了!
为什么会报错呢?
如果我们把该语句转换为not in的方式:
根据not in的逻辑,此时在fee_code前应该加上’A.’,当然这也是没有问题的,但是,再次看这条语句就会变成:
由于TMP_APP_xxx_PREM A 中并没有FEE_CODE字段, 所以,Not in 无法自动改成Null Aware ANTI JOIN。
所以,至此答案揭晓,竟然是写错了?!我猜中了这开头,却没有猜中这结局。
但在本案例中,由于SQL语句中没有显式写出表明,导致在前期分析过程中一直没有发现这个错误。
你是不是也很无语,其实我更想问的是,你是不是也经常写出杀手SQL呢,但没关系,你有病我有药啊。(无辜脸,不要打我)
我们都知道,在 DBA 所优化的数据库环境中,绝大多数性能问题其实是由于 SQL 编写不当导致的。
对于未上线系统,通过前期的SQL审核管控,将80%的SQL问题消灭在萌生阶段,对于线上运行系统,发现和解决潜在的性能问题,可做到提前预防,防患于未然。
SQL审核,让DBA由系统的急救医生转身成为系统的保健医生
1、DBA参与应用代码开发测试过程:给开发人员提供专业的数据库开发及优化建议
2、优化前置:在应用代码上线前根据业务需求设计高效的SQL、索引
3、控制变更风险:预先评估应用开发中表结构变更、SQL变更对运行中应用的影响,确定合适的变更窗口,变更方案。
以上就是优化 SQL 查询,减少‘Not in' 运行时间的详细内容,更多请关注慧达安全导航其它相关文章!
免责 声明
1、本网站名称:慧达安全导航
2、本站永久网址:https//www.huida178.com/
3、本站所有资源来源于网友投稿和高价购买,所有资源仅对编程人员及源代码爱好者开放下载做参考和研究及学习,本站不提供任何技术服务!
4、本站所有资源的属示图片和信息不代表本站的立场!本站只是储蓄平台及搬运
5、下载者禁止在服务器和虚拟机下进行搭建运营,本站所有资源不支持联网运行!只允许调试,参考和研究!!!!
6、未经原版权作者许可禁止用于任何商业环境,任何人不得擅作它用,下载者不得用于违反国家法律,否则发生的一切法律后果自行承担!
7、为尊重作者版权,请在下载24小时内删除!请购买原版授权作品,支持你喜欢的作者,谢谢!
8.若资源侵犯了您的合法权益,请持 您的版权证书和相关原作品信息来信通知我们!QQ:1247526623我们会及时删除,给您带来的不便,我们深表歉意!
9、如下载链接失效、广告或者压缩包问题请联系站长处理
10、如果你也有好源码或者教程,可以发布到网站,分享有金币奖励和额外收入!
11、本站资源售价只是赞助,收取费用仅维持本站的日常运营所需
12、因源码具有可复制性,一经赞助,不得以任何形式退款。
13、本文内容由网友自发贡献和站长收集,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系1247526623@qq.com
转载请注明出处: 慧达安全导航 » 优化 SQL 查询,减少‘Not in' 运行时间
发表评论 取消回复