能写在 WHERE 子句里的条件不要写在 HAVING 子句里我们来看两个 SQL 以及其执行结果

文章插图
从结果上来看 , 两条 SQL 一样;但是从性能上来看 , 第二条语句写法效率更高 , 原因有两个
减少排序的数据量
GROUP BY 子句聚合时会进行排序 , 如果事先通过 WHERE 子句筛选出一部分行 , 就能够减轻排序的负担
有效利用索引
WHERE 子句的条件里可以使用索引
HAVING 子句是针对聚合后生成的视图进行筛选的 , 但是很多时候聚合后的视图都没有继承原表的索引结构
关于 HAVING , 更多详情可查看:神奇的 SQL 之 HAVING → 容易被轻视的主角
在 GROUP BY 子句和 ORDER BY 子句中使用索引一般来说 , GROUP BY 子句和 ORDER BY 子句都会进行排序
如果 GROUP BY 和 ORDER BY 的列有索引 , 那么可以提高查询效率
特别是在一些数据库中 , 如果列上建立的是唯一索引 , 那么排序过程本身都会被省略掉
使用索引使用索引是最常用的 SQL 优化手段 , 这个大家都知道 , 怕就怕大家不知道:明明有索引 , 为什么查询还是这么慢(为什么索引没用上)
关于索引未用到的情况 , 可查看:神奇的 SQL 之擦肩而过 → 真的用到索引了吗 , 本文就不做过多阐述了
总之就是:查询尽量往索引上靠 , 规避索引未用上的情况
减少临时表在 SQL 中 , 子查询的结果会被看成一张新表(临时表) , 这张新表与原始表一样 , 可以通过 SQL 进行操作
但是 , 频繁使用临时表会带来两个问题
1、临时表相当于原表数据的一份备份 , 会耗费内存资源
2、很多时候(特别是聚合时) , 临时表没有继承原表的索引结构
因此 , 尽量减少临时表的使用也是提升性能的一个重要方法
灵活使用 HAVING 子句对聚合结果指定筛选条件时 , 使用 HAVING 子句是基本原则
但是如果对 HAVING 不熟 , 我们往往找出替代它的方式来实现 , 就像这样

文章插图
然而 , 对聚合结果指定筛选条件时不需要专门生成中间表 , 像下面这样使用 HAVING 子句就可以

文章插图
HAVING 子句和聚合操作是同时执行的 , 所以比起生成临时表后再执行 WHERE 子句 , 效率会更高一些 , 而且代码看起来也更简洁
需要对多个字段使用 IN 谓词时 , 将它们汇总到一处SQL-92 中加入了行与行比较的功能 , 这样一来 , 比较谓词 = 、< 、> 和 IN 谓词的参数就不再只是标量值了 , 而应是值列表了
我们来看一个示例 , 多个字段使用 IN 谓词

文章插图
这段代码中用到了两个子查询 , 我们可以进行列汇总优化 , 把逻辑写在一起

文章插图
这样一来 , 子查询不用考虑关联性 , 而且只执行一次就可以
还可以进一步简化 , 在 IN 中写多个字段的组合

文章插图
简化后 , 不用担心连接字段时出现的类型转换问题 , 也不会对字段进行加工 , 因此可以使用索引
先进行连接再进行聚合连接和聚合同时使用时 , 先进行连接操作可以避免产生中间表
合理地使用视图视图是非常方便的工具 , 我们在日常工作中经常使用
但是 , 如果没有经过深入思考就定义复杂的视图 , 可能会带来巨大的性能问题
特别是视图的定义语句中包含以下运算的时候 , SQL 会非常低效 , 执行速度也会变得非常慢

文章插图
总结文中虽然列举了几个要点 , 但其实优化的核心思想只有一个 , 那就是找出性能瓶颈所在 , 然后解决它
推荐阅读
- 视频短片是怎样拍摄制作出来的?需要怎样的流程?
- 用 Loki 和 fzf 进阶你的 Shell 历史记录
- 为什么隋唐演义中有罗成,又有罗士信 历史上的罗士信是傻子吗
- 桃花源记是陶渊明想象的吗 陶渊明在桃花源记中表现桃花源人什么
- 雍正对李卫有多信任 李卫是雍正的什么人
- 第二次鸦片战争的爆发有何关联 第二次鸦片战争的爆发时间
- 明朝被李自成打败的还是清朝打败的 李自成与清军大战为何大败
- 六堡茶祛湿效果怎么样,六堡茶的功效介绍
- 庐山云雾的特点先容,庐山云雾作用及功效介绍
- 百合花花茶的功效,百合花茶百合花茶的作用和功效
