性能优化实战-join与where条件执行顺序
昨天经历了一场非常痛苦的性能调优过程,但是收获也是刻骨铭心的,感觉对sql引擎的原理有了进一步认识。
问题起源于测试人员测一个多条件检索的性能时,发现按某个条件查询会特别慢。对应的sql语句简化为:
- select * from ta a,tb b
- where a.bid=b.id
- and a.col1='xx'
- and b.col2='yy'
- and dbo.func(a.col3,'zz')=1
ta表几万行,tb几百行。
大家看到了,慢的那个条件就是"and dbo.func(a.col3,'zz')=1". 这里用到自定义函数是迫不得已的,原因暂且不表。所以当qa只用a.col3查的时候,需要遍历ta表,对每一行应用函数,不慢才怪 呢。由于a.col3不是主要条件,qa就不跟我纠结这个问题了。但是qa又用b.col2和a.col3一起查询,最终结果才几十条,为什么还是非常慢。我说sql估计还是先全表执行了那个函数,所以还是慢。qa说无法接受,然后提了个bug。
其实我也非常纳闷,为啥sql引擎会制定出那么sx的执行计划,明明先用b.col2过滤,再做表连接,再去用函数过滤,该多好?!没办法,我只好耐下心来,研究执行计划。
看了计划发现,ta条件和tb的条件是并行过滤的,过滤完之后再做连接。我开始考虑,能不能做点什么,让sql按想要的步骤来走。于是:
1. 在a.col1上加了索引,发现没啥提升,原来a.col1='xx'并没有过滤掉多少数据。
2. 在b.col2上加了索引,也没提升,依然是函数执行完毕后才连接。
3. 在a.col3上建索引?a.col3是个复杂文本,建索引没有任何意义。
4. 把写法改为join,并且把各个条件在on和where之间来回倒腾,没用。
5. 想把函数加个with schemabinding, 但放弃了,这个函数的性能其实已经到极限了,指定架构的话,怕是没什么提升,而且又加了额外的限制,不妥。
6. 想加一个undocument的查询提示,不让它并行过滤。既然select末尾加上OPTION (QUERYTRACEON 8649)可以强制并行,那我把8649换成其他数字能强制不走并行吗?换了好几个,都没用。后来才发现,这个querytraceon的并行和本文的并行没有半毛钱关系。
7. 使用嵌套查询。加一层select * from,把func条件提到外层来。按道理,func应该最后过滤了吧!结果,还是一样的执行计划。我是该夸sql engine太智能呢,还是该骂它太sb呢?
8. 准备在代码里动手脚,结果代码冻结了……只准改sql。
manager说今天必须搞定,不然影响今天发包。
黔驴技穷。四面楚歌。
无计可施了,我只能做点边边角角的事情,想把整体性能再弄好一点,比如,许多重要的索引在当前的新库上都没建好,于是我就一个个补上去,其中包括a.bid上的索引。这时候,奇迹发生了,那个很慢的查询突然变得飞快!!!在那一刻,我顿悟了,为什么之前一直是最后才进行表连接?因为sql engine啃不动func这个东西,连接条件上又没有索引,所以只好按常规套路,先执行各表的过滤条件,尽量让待连接的行数减到最小,最后再做关联。
至此,问题解决:)
总结一下:
1. 关联字段上的索引非常重要。
2. 把条件放在(inner)join-on或者where后面,以及条件的先后顺序,对效率影响不大(仅针对Sqlserver)。但我个人习惯是,两表连接条件放在join-on后面,各表自己的过滤条件放在where后面,尊重语义,易读易维护。
性能优化实战-join与where条件执行顺序的更多相关文章
- 优化 : Oracle数据库Where条件执行顺序 及Where子句的条件顺序对性能的影响
.Oracle数据库Where条件执行顺序: 由于SQL优化起来比较复杂,并且还会受环境限制,在开发过程中,写SQL必须必须要遵循以下几点的原则: 1.ORACLE采用自下而上的顺序解析WHERE子句 ...
- Golang 性能优化实战
小结: 1. 性能查看工具 pprof,trace 及压测工具 wrk 或其他压测工具的使用要比较了解. 代码逻辑层面的走读非常重要,要尽量避免无效逻辑. 对于 golang 自身库存在缺陷的,可以寻 ...
- 网站性能优化实战——从12.67s到1.06s的故事
文章摘自https://juejin.im/post/5b0b7d74518825158e173a0c 作为互联网项目,最重要的便是用户体验.在举国“互联网+”的热潮中,用户至上也已经被大多数企业所接 ...
- 小程序Canvas性能优化实战
以下内容转载自totoro的文章<小程序Canvas性能优化实战!> 作者:totoro 链接:https://blog.totoroxiao.com/canvas-perf-mini/ ...
- 我把阿里、腾讯、字节跳动、美团等Android性能优化实战整合成了一个PDF文档
安卓开发大军浩浩荡荡,经过近十年的发展,Android技术优化日异月新,如今Android 11.0 已经发布,Android系统性能也已经非常流畅,可以在体验上完全媲美iOS. 但是,到了各大厂商手 ...
- 什么时候出现死锁,如何解决?mysql 引擎? 多个like or 查询sql如何优化?什么是常量池?for条件执行顺序
1. 什么时候出现死锁,如何解决?mysql 引擎? 多个like or 查询sql如何优化? 资源竞争导致死锁,比如A B 同时操作两条记录,并等待对方释放锁. 优化sql, 加缓存,主从(如读写分 ...
- ORACLE中查询语句的执行顺及where部分条件执行顺序测试
Oracle中的一些查询语句及其执行顺序 原文地址:https://www.cnblogs.com/likeju/p/5039115.html 查询条件: 1)LIKE:模糊查询,需要借助两个通配符, ...
- 从join on和where执行顺序认识T-SQL查询处理执行顺序
先从一例子看join on 和 where执行结果的不同 CREATE TABLE "SCOTT"."A" ( "PERSON_ID" ) ...
- MySQL查询语句执行过程及性能优化(JOIN/ORDER BY)-图
http://blog.csdn.net/iefreer/article/details/12622097 MySQL查询语句执行过程及性能优化-查询过程及优化方法(JOIN/ORDER BY) 标签 ...
随机推荐
- 互联网汽车迎新成员 Alibaba YunOS Auto冠名2016世俱杯
11月18日广州车展现场,阿里巴巴集团再次携手上汽集团连发三款搭载YunOS系统的互联网汽车,包括MG ZS.荣威eRX5和荣威i6.同时阿里巴巴集团YunOS总裁张春晖正式宣布互联网汽车业务全新升级 ...
- layui 时间控件 单击 年直接赋值
在 //选中 lay(ul).find('li').on('click', function(){ //结尾处添加 if (options.done === "year") { ...
- Javaee 方法的格式和注意事项
1.构造方法的格式是什么?有哪些注意事项? 修饰符+方法名称+(参数列表),构造的方法没有返回值,方法名称要和类名一样,有属性参数的需要在成员变量前加this,参数列表的值要和指定的方法格式相同. ...
- K3 销售合同开发
1.实现销售合同中[直接客户]信息的录入后,自动带出关联[省份]的信息,根据BOS单据的基本设置不能将省份信息写成字 段进行推送,故需要在BOS单据中进行插件开发: 开发过程中有个关键表: 1)选择直 ...
- keepalived+mysql主主实现高可用
mysql主从配置参考我的上篇博客 主主配置就是互为主从 环境 准备应用 keepalived-2.0.2.tar.gz openssl-devel-1.0.2k-12.el7.x86_64.rpm ...
- UVA-11806 Cheerleaders 计数问题 容斥定理
题目链接:https://cn.vjudge.net/problem/UVA-11806 题意 在一个mn的矩形网格里放k个石子,问有多少方法. 每个格子只能放一个石头,每个石头都要放,且第一行.最后 ...
- nyoj312-20岁生日
20岁生日 时间限制:1000 ms | 内存限制:65535 KB 难度:1 描述 路过这的20岁生日就要到了,他当然很开心,可是他突然想到一个问题,是不是每个人从出生开始,到达20岁生日时所经 ...
- [模板] zkw线段树
zkw线段树 code1简单版本 code2差分版本(暂无) code1:(有注释) //By Menteur_Hxy #include<cstdio> #include<iostr ...
- [tyvj-1071]LCIS 动态规划
LCIS模板 #include <cstdio> #include <cstring> #include <iostream> using namespace st ...
- BeanPostProcessor bean 的后置处理器
一. 自定 bean 的后置处理器 MyBeanPostProcessor 类.当你在初始化容器中的 bean 之前和之后,都会调用该处理器中的方法 @Component //将该后后置处理器加入到容 ...