MySQL优化的奇技淫巧之STRAIGHT_JOIN
原文地址:http://huoding.com/2013/06/04/261
问题
通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下:
SELECT post.*
FROM post
INNER JOIN post_tag ON post.id = post_tag.post_id
WHERE post.status = 1 AND post_tag.tag_id = 123
ORDER BY post.created DESC
LIMIT 100
说明:因为post和tag是多对多的关系,所以存在一个关联表post_tag。
试着用EXPLAIN查询一下SQL执行计划(篇幅所限,结果有删减):
+----------+---------+-------+-----------------------------+
| table | key | rows | Extra |
+----------+---------+-------+-----------------------------+
| post_tag | tag_id | 71220 | Using where; Using filesort |
| post | PRIMARY | 1 | Using where |
+----------+---------+-------+-----------------------------+
下面给出优化后的SQL,唯一的变化就是把连接方式改成了「STRAIGHT_JOIN」:
SELECT post.*
FROM post
STRAIGHT_JOIN post_tag ON post.id = post_tag.post_id
WHERE post.status = 1 AND post_tag.tag_id = 123
ORDER BY post.created DESC
LIMIT 100
试着用EXPLAIN查询一下SQL执行计划(篇幅所限,结果有删减):
+----------+----------------+--------+-------------+
| table | key | rows | Extra |
+----------+----------------+--------+-------------+
| post | status_created | 119340 | Using where |
| post_tag | post_id | 1 | Using where |
+----------+----------------+--------+-------------+
对比优化前后两次EXPLAIN的结果来看,优化后的SQL虽然「rows」更大了,但是没有了「Using filesort」,综合来看,性能依然得到了提升。
提醒:注意两次EXPLAIN结果中各个表出现的先后顺序,稍后会解释。
解释
对第一条SQL而言,为什么MySQL优化器选择了一个耗时的执行方案?对第二条SQL而言,为什么把连接方式改成STRAIGHT_JOIN之后就提升了性能?
这一切还得从MySQL对多表连接的处理方式说起,首先MySQL优化器要确定以谁为驱动表,也就是说以哪个表为基准,在处理此类问题时,MySQL优化器采用了简单粗暴的解决方法:哪个表的结果集小,就以哪个表为驱动表,当然MySQL优化器实际的处理方式会复杂许多,具体可以参考:MySQL优化器如何选择索引和JOIN顺序。
说明:在EXPLAIN结果中,第一行出现的表就是驱动表。
继续post连接post_tag的例子,MySQL优化器有如下两个选择,分别是:
- 以post为驱动表,通过status_created索引过滤,结果集119340行
- 以post_tag为驱动表,通过tag_id索引过滤,结果集71220行
显而易见,post_tag过滤的结果集更小,所以MySQL优化器选择它作为驱动表,可悲催的是我们还需要以post表中的created字段来排序,也就是说排序字段不在驱动表里,于是乎不可避免的出现了「Using filesort」,甚至「Using temporary」。
知道了来龙去脉,优化起来就容易了,要尽可能的保证排序字段在驱动表中,所以必须以post为驱动表,于是乎必须借助「STRAIGHT_JOIN」强制连接顺序。
实际上在某些特殊情况里,排序字段可以不在驱动表里,比如驱动表结果集只有一行记录,并且在连接其它表时,索引除了连接字段,还包含了排序字段,此时连接表后,索引中的数据本身自然就是排好序的。
既然聊到这里顺带说点题外话,大家可能会遇到类似下面的问题:原本运行良好的查询语句,过了一段时间后,可能会突然变得很糟糕。一个很大可能的原因就是数据分布情况发生了变化,从而导致MySQL优化器对驱动表的选择发生了变化,进而出现索引失效的情况,所以没事最好多查查,关注一下这些情况。
…
对于「STRAIGHT_JOIN」,我总觉得这种非标准的语法属于奇技淫巧的范畴,能不用尽量不用,毕竟多数情况下,MySQL优化器都能做出正确的选择。
MySQL优化的奇技淫巧之STRAIGHT_JOIN的更多相关文章
- 0111MySQL优化的奇技淫巧之STRAIGHT_JOIN
转自博客http://huoding.com/2013/06/04/261 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: SELECT post.* F ...
- [转] MySql 优化 大数据优化
一.我们可以且应该优化什么? 硬件 操作系统/软件库 SQL服务器(设置和查询) 应用编程接口(API) 应用程序 ------------------------------------------ ...
- 项目中常用的19条MySQL优化
声明一下:下面的优化方案都是基于 " Mysql-索引-BTree类型 " 的 一.EXPLAIN 做MySQL优化,我们要善用 EXPLAIN 查看SQL执行计划. 下面来个简单 ...
- 19条MySQL优化准则
1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我们要重点关注的数据: type列,连接类型.一个好的SQL语句至少要 ...
- 巧用这19条MySQL优化,效率至少提高3倍
阅读本文大概需要 3.8 分钟. 作者丨喜欢拿铁的人 https://zhuanlan.zhihu.com/p/49888088 本文我们来谈谈项目中常用的MySQL优化方法,共19条,具体如下: 1 ...
- 项目中常用的MySQL 优化
本文我们来谈谈项目中常用的MySQL优化方法,共19条,具体如下: 一.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我 ...
- 巧用这19条MySQL优化【转】
1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我们要重点关注的数据: type列,连接类型.一个好的SQL语句至少要 ...
- SQL学习笔记之项目中常用的19条MySQL优化
在写文章之前,首先感谢 飞友科技 陆老师提供的文档.. 声明一下:下面的优化方案都是基于 “ Mysql-索引-BTree类型 ” 的 0x00 EXPLAIN 做MySQL优化,我们要善用 EXPL ...
- 项目中常用的MySQL优化方法--壹拾玖条
1.EXPLAIN 做MySQL优化,我们要善用EXPLAIN查看SQL执行计划. 下面来个简单的示例,标注(1.2.3.4.5)我们要重点关注的数据: type列,连接类型.一个好的SQL语句至少要 ...
随机推荐
- Ubuntu1404 (1)
0.初始设置 (1)开户root账号并重启系统: sudo gedit /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf, 添加greeter-show ...
- eclipse 添加 hibernate 插件
eclipse helios(3.6)版 1.启动eclipse 2.选择Help > Install New Software...> 3.添加如下地址:http://download. ...
- Oauth2.0
注:Access token 为第三方平台的token,在用户授权时使用Refresh Token为用户的token get/post参数时,一般采用字典排序
- (转)打印相关_C#图片处理Bitmap位图缩放和剪裁
原文地址:http://blog.sina.com.cn/s/blog_6427a6b50101el9d.html 在GDI+中,缩放和剪裁可以看作同一个操作,无非就是原始区域的选择不同罢了. /// ...
- Erlang 参考资料
Erlang 官方文档 Distributed Erlang Erlang 教程中文版 %设定模块名 -module(tut17). %导出相关函数 -export([start_ping/1, st ...
- 无需写try/catch,也能正常处理异常 (转)
原文地址: http://www.cnblogs.com/artech/archive/2012/10/28/automatic-exception-handling-aspnet.html 对于企业 ...
- MyEclipse 激活
2014版,需要注意的几个问题: 1.安装路径不要有空格: 2.输入usercode-systemid-tools rebyild-active-tools replace-tools-save; 3 ...
- oracle 执行 delete user$ 误删所有用户信息后的数据恢复流程
起因: 在oracle测试过程中,不小心执行了delete user$ 命令,导致oracle当前实例所有的用户信息丢失,包括sys用户. 第一次使用DUL工具数据恢复:失败 下载ParnassusD ...
- Nopcommerce 二次开发0
Nopcommerce 是国外的一个高质量的开源b2c网站系统,基于EntityFramework6.0和MVC5.0,使用Razor模板引擎,有很强的插件机制,包括支付配送功能都是通过插件来实现的 ...
- install cx_Oracle on Linux
step 1 : install oracle client library url: http://www.oracle.com/technetwork/topics/linuxsoft-08280 ...