昨天经历了一场非常痛苦的性能调优过程,但是收获也是刻骨铭心的,感觉对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. a rel=noopener

    看vue-element-admin的源码的时候,看到a 标签使用  rel=noopener: 然后就很奇怪这个是干什么用的:然后百度到一篇文章,涨知识了. 个人的理解是:不加 rel=noopen ...

  2. hibernate一对多和多对一配置

    public class Dept { private int deptId; private String deptName; // [一对多] 部门对应的多个员工 private Set<E ...

  3. 查看Linux系统版本信息的几种方法

    一.查看Linux内核版本命令(两种方法): 1.cat /proc/version 2.uname -a 二.查看Linux系统版本的命令(3种方法): 1.lsb_release -a,即可列出所 ...

  4. 【JavaScript框架封装】实现一个类似于JQuery的事件框架的封装

    // 事件框架 (function (xframe) { // 需要参与链式访问的(必须使用prototype的方式来给对象扩充方法) xframe.extend({ /** * 实现一个浏览器的基本 ...

  5. HDU 1164 Eddy's research I( 试除法 & 筛法改造试除法 分解整数 )

    链接:传送门 题意:给出一个整数 n ,输出整数 n 的分解成若干个素因子的方案 思路:经典的整数分解题目,这里采用试除法 和 用筛法改造后的试除法 对正整数 n 进行分解 方法一:试除法对正整数 n ...

  6. Tensorboard服务激活

    首先确定Tensorflow的具体位置(在Dos环境下,也就是cmd) cd .. cd scripts conda env list activate tensorflow tensorboard ...

  7. 【hdu 6438】Buy and Resell

    [链接] 我是链接,点我呀:) [题意] 有一个物品的价格在1..n这些位置各不相同. 你初始有无限的钱. 问你从1走到n. 你每次可以选择买入一个或者卖出一个该种物品(或啥都不做) 问你最后的最大利 ...

  8. ActiveMQ 发送和接收消息

    一.添加 jar 包 <dependency> <groupId>org.apache.activemq</groupId> <artifactId>a ...

  9. Ubuntu 15.10配置OpenCV

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50635705 1 安装前准备 安装以下 ...

  10. [Office]PPT 2013如何设置图片为半透明?

    PPT里面似乎无法直接为图片设置透明度属性.下面是一种变通的办法. 1,插入一个和图片大小一致的图形(矩形):2,右键插入的矩形,然后在属性设置里选择“图片填充”,选择以需要的图片填充到该矩形里:3, ...