昨天经历了一场非常痛苦的性能调优过程,但是收获也是刻骨铭心的,感觉对sql引擎的原理有了进一步认识。

问题起源于测试人员测一个多条件检索的性能时,发现按某个条件查询会特别慢。对应的sql语句简化为:

  1. select * from ta a,tb b
  2. where a.bid=b.id
  3. and a.col1='xx'
  4. and b.col2='yy'
  5. 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条件执行顺序的更多相关文章

  1. 优化 : Oracle数据库Where条件执行顺序 及Where子句的条件顺序对性能的影响

    .Oracle数据库Where条件执行顺序: 由于SQL优化起来比较复杂,并且还会受环境限制,在开发过程中,写SQL必须必须要遵循以下几点的原则: 1.ORACLE采用自下而上的顺序解析WHERE子句 ...

  2. Golang 性能优化实战

    小结: 1. 性能查看工具 pprof,trace 及压测工具 wrk 或其他压测工具的使用要比较了解. 代码逻辑层面的走读非常重要,要尽量避免无效逻辑. 对于 golang 自身库存在缺陷的,可以寻 ...

  3. 网站性能优化实战——从12.67s到1.06s的故事

    文章摘自https://juejin.im/post/5b0b7d74518825158e173a0c 作为互联网项目,最重要的便是用户体验.在举国“互联网+”的热潮中,用户至上也已经被大多数企业所接 ...

  4. 小程序Canvas性能优化实战

    以下内容转载自totoro的文章<小程序Canvas性能优化实战!> 作者:totoro 链接:https://blog.totoroxiao.com/canvas-perf-mini/ ...

  5. 我把阿里、腾讯、字节跳动、美团等Android性能优化实战整合成了一个PDF文档

    安卓开发大军浩浩荡荡,经过近十年的发展,Android技术优化日异月新,如今Android 11.0 已经发布,Android系统性能也已经非常流畅,可以在体验上完全媲美iOS. 但是,到了各大厂商手 ...

  6. 什么时候出现死锁,如何解决?mysql 引擎? 多个like or 查询sql如何优化?什么是常量池?for条件执行顺序

    1. 什么时候出现死锁,如何解决?mysql 引擎? 多个like or 查询sql如何优化? 资源竞争导致死锁,比如A B 同时操作两条记录,并等待对方释放锁. 优化sql, 加缓存,主从(如读写分 ...

  7. ORACLE中查询语句的执行顺及where部分条件执行顺序测试

    Oracle中的一些查询语句及其执行顺序 原文地址:https://www.cnblogs.com/likeju/p/5039115.html 查询条件: 1)LIKE:模糊查询,需要借助两个通配符, ...

  8. 从join on和where执行顺序认识T-SQL查询处理执行顺序

    先从一例子看join on 和 where执行结果的不同 CREATE TABLE "SCOTT"."A" ( "PERSON_ID" ) ...

  9. MySQL查询语句执行过程及性能优化(JOIN/ORDER BY)-图

    http://blog.csdn.net/iefreer/article/details/12622097 MySQL查询语句执行过程及性能优化-查询过程及优化方法(JOIN/ORDER BY) 标签 ...

随机推荐

  1. C# 取web应用程序运行目录

    HttpRuntime.AppDomainAppPath

  2. 怎么让composer加速(转)

    composer 在install的时候会做这几个事情: 去packagist.org中寻找对应需要的包的版本信息和下载地址 循环下载对应的包 解压安装对应的包 我们平时使用composer慢就可能在 ...

  3. js中标签字符串的拼接

    //1.用单双引号拼接 var valueDemo = "111"; var htmlStrs1 = '<option selected="selected&quo ...

  4. 佛祖保佑,永不宕机,永无 Bug

    转自:http://top.jobbole.com/17580/ 佛祖保佑,永不宕机,永无 Bug 为何服务器频遭黑客攻击?为何系统频频宕机,别人家系统却稳如泰山,坚如磐石?为何运维人员和系统管理员行 ...

  5. call和apply的使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. nyoj56-阶乘因式分解(一)

    56-阶乘因式分解(一) 内存限制:64MB时间限制:3000msSpecial Judge: No accepted:6submit:7 题目描述: 给定两个数m,n,其中m是一个素数. 将n(0& ...

  7. 51nod-独木舟问题

    n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟?分析:  一个显然的策略 ...

  8. Mysql 忘记数据库密码

    windows下忘记MySQL密码的修改方法 1.关闭正在运行的Mysql服务: A.命令下运行   net stop mysql B.找到mysql服务停止mysql的服务 C.在任务管理器中结束M ...

  9. php文件上传相关知识点回顾

    近来正在回顾PHP的文件上传.在此做个记录. <?php date_default_timezone_set('PRC'); if(isset($_POST['submit'])) { echo ...

  10. python第六周:面向对象编程

    面向对象编程: 世界万物,皆可分类 世界万物,对象 只要是对象,就肯定属于某种品类 只要是对象,就肯定有属性 oop编程利用"类"和"对象"来创建各种模型来实现 ...