性能优化实战-join与where条件执行顺序

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

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

[sql] view plain copy

print?

  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后面,尊重语义,易读易维护。

时间: 2024-10-10 09:06:27

性能优化实战-join与where条件执行顺序的相关文章

面向.Net程序员的后端性能优化实战

最近2个月没做什么新项目 完全是对于旧的系统进行性能优化 避免超时 死锁 数据处理能力不够等常见的性能问题 这里不从架构方面出发 毕竟动大手脚成本比较高 那么我们以实例为前提 从细节开始 优化角度 一.业务逻辑优化 二.DB优化 三.数据处理优化 四.锁与性能 五.cpu飙高小结 六.crash现象分析 业务逻辑优化 这一条不具有普遍性 不同的业务不同的场景 如果归纳起来 就是在不影响业务的前提下进行流程精简 1. 废弃冗余逻辑 常见于各种基于数据库的检查 很多同学在维护别人代码的时候 没有深入

蚂蚁金服架构师带你深入性能优化一MySql性能优化实战

概要: Mysql的优化,大体可以分为三部分:索引的优化,sql语句的优化,表的优化.本文主要帮助自己整理思路,也可作为一个学习MySQL优化的提纲. 索引的优化 只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引 尽量使用短索引,如果可以,应该制定一个前缀长度 对于经常在where子句使用的列,最好设置索引,这样会加快查找速度 对于有多个列where或者order by子句的,应该建立复合索引 对于like语句,以%或者'-'开头的不会使用索

从细节出发 纯后端性能优化实战小结

最近2个月没做什么新项目 完全是对于旧的系统进行性能优化 避免超时 死锁 数据处理能力不够等常见的性能问题 这里不从架构方面出发 毕竟动大手脚成本比较高 那么我们以实例为前提 从细节开始 优化角度 一.业务逻辑优化 二.DB优化 三.数据处理优化 四.锁与性能 五.细节 业务逻辑优化 这一条不具有普遍性 不同的业务不同的场景 如果归纳起来 就是在不影响业务的前提下进行流程精简 1. 废弃冗余逻辑 常见于各种基于数据库的检查 很多同学在维护别人代码的时候 没有深入理解别人的逻辑 也许别人在取数据的

SQL Server SQL性能优化之--通过拆分SQL提高执行效率,以及性能高低背后的原因

复杂SQL拆分优化 拆分SQL是性能优化一种非常有效的方法之一, 具体就是将复杂的SQL按照一定的逻辑逐步分解成简单的SQL,借助临时表,最后执行一个等价的逻辑,已达到高效执行的目的 一直想写一遍通过拆分SQL来优化的博文,最近刚好遇到一个实际案例,比较有代表性,现分享出来, 我们来通过一个案例来分析,为什么拆分语句可以提高SQL执行效率,更重要的是弄清楚,拆分前为什么慢,拆分后为什么快了? 幼稚的话,各位看官莫笑 先看一下相关表的数据量,大表也有5900多万,小表有160多万 (声明:我从来没

android性能优化实战理论篇

本文地址:http://blog.csdn.net/iamws/article/details/51636175 第二篇:理论 通过之前前篇介绍的工具,我们知道了应该怎么样去获取要分析的数据,但是也仅仅局限在于怎么样获取数据,而没有深入数据分析,这一篇主要讲解的是UI刷新这块部分android理论知识,有了这些知识后,对于上面的数据该怎么分析,你就胸有成竹了. ps:本文只是个人理解后的总结,并不会深入源码层次分析,如有错误,还请麻烦各位帮忙指正~ 这篇文章要解决的理论问题如下: 1.什么是内存

扫‘雷’ 纯后端性能优化实战(已合下篇)

最近2个月没做什么新项目 完全是对于旧的系统进行性能优化 避免超时 死锁 数据处理能力不够等常见的性能问题 这里不从架构方面出发 毕竟动大手脚成本比较高 那么我们以实例为前提 从细节开始 优化角度 一.业务逻辑优化 二.DB优化 三.数据处理优化 四.锁与性能 五.cpu飙高小结 六.crash现象分析 业务逻辑优化 这一条不具有普遍性 不同的业务不同的场景 如果归纳起来 就是在不影响业务的前提下进行流程精简 1. 废弃冗余逻辑 常见于各种基于数据库的检查 很多同学在维护别人代码的时候 没有深入

Android ListView性能优化实战方案

前言: 对于ListView,大家绝对都不会陌生,只要是做过Android开发的人,哪有不用ListView的呢? 只要是用过ListView的人,哪有不关心对它性能优化的呢? 关于如何对ListView进行性能优化,不仅是面试中常常会被问到的(我前段时间面试了几家公司,全部都问到了这个问题了),而且在实际项目中更是非常重要的一环,它甚至在某种程度上决定了用户是否喜欢接受你的APP.(如果你的列表滑起来很卡,我敢说很多人会直接卸载) 网上关于如何对ListView进行性能优化,提出了很多方案.但

Android UI性能优化实战 识别绘制中的性能问题

出自:[张鸿洋的博客]来源:http://blog.csdn.net/lmj623565791/article/details/45556391 1.概述 2015年初google发布了Android性能优化典范,发了16个小视频供大家欣赏,当时我也将其下载,通过微信公众号给大家推送了百度云的下载地址(地址在文末,ps:欢迎大家订阅公众号),那么近期google又在udacity上开了系列类的相关课程.有了上述的参考,那么本性能优化实战教程就有了坚实的基础,本系列将结合实例为大家展示如何去识别.

Linux性能优化实战: Linux 性能优化答疑(四)(32)

一.上节总结 专栏更新至今,四大基础模块的第三个模块——文件系统和磁盘 I/O 篇,我们就已经学完了.很开心你还没有掉队,仍然在积极学习思考和实践操作,并且热情地留言与讨论. 今天是性能优化的第四期.照例,我从 I/O 模块的留言中摘出了一些典型问题,作为今天的答疑内容,集中回复.同样的,为了便于你学习理解,它们并不是严格按照文章顺序排列的. 每个问题,我都附上了留言区提问的截屏.如果你需要回顾内容原文,可以扫描每个问题右下方的二维码查看. 二.问题 1:阻塞.非阻塞 I/O 与同步.异步 I/