0111MySQL优化的奇技淫巧之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优化器都能做出正确的选择。
0111MySQL优化的奇技淫巧之STRAIGHT_JOIN的更多相关文章
- MySQL优化的奇技淫巧之STRAIGHT_JOIN
原文地址:http://huoding.com/2013/06/04/261 问题 通过「SHOW FULL PROCESSLIST」语句很容易就能查到问题SQL,如下: SELECT post.* ...
- [慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
写在前面的话: 不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程: 不要求每个人一定知道线上(现在或未来)哪张表数据量大,哪张表数据量小: ...
- 【转】[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定
转自:http://zhengyun-ustc.iteye.com/blog/1942797 写在前面的话: 不要求每个人一定理解 联表查询(join/left join/inner join等)时的 ...
- 浅谈SQL优化入门:2、等值连接和EXPLAIN(MySQL)
1.等值连接:显性连接和隐性连接 在<MySQL必知必会>中对于等值连接有提到两种方式,第一种是直接在WHERE子句中规定如何关联即可,那么第二种则是使用INNER JOIN关键字.如下例 ...
- (转)MySQL join语法解析与性能分析
文章转载的:http://www.cnblogs.com/BeginMan/p/3754322.html 一.join语法概述 join用于多表中字段之间的联系,语法如下: ... FROM tabl ...
- mysql的join操作
一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...
- [转]Mysql Join语法解析与性能分析
转自:http://www.cnblogs.com/BeginMan/p/3754322.html 一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 ...
- Java并发编程常识
这是why的第 85 篇原创文章 写中间件经常要做两件事: 1.延迟加载,在内存缓存已加载项. 2.统计调用次数,拦截并发量. 就这么个小功能,团队里的人十有八九写错. 上面这句话不是我说的,是梁飞在 ...
- MySQL性能优化奇技淫巧
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使 ...
随机推荐
- JSTL函数标签
tld 文件代码 <?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="ht ...
- nyoj--491--幸运三角形(dfs)
幸运三角形 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 话说有这么一个图形,只有两种符号组成('+'或者'-'),图形的最上层有n个符号,往下个数依次减一,形成倒置的 ...
- 【JSOI 2008】 球形空间产生器
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1013 [算法] 高斯消元 [代码] #include<bits/stdc++. ...
- Node.js:JXcore
ylbtech-Node.js:JXcore 1.返回顶部 1. Node.js JXcore 打包 Node.js 是一个开放源代码.跨平台的.用于服务器端和网络应用的运行环境. JXcore 是一 ...
- x+=y与x=x+y相同吗?
为了将赋值操作简便化,Java提供了很多扩展赋值运算符,例如+=.-=./=.*=等等,那么问题来了,x += 1与x = x +1两者相同吗? public class EqualsTest { @ ...
- lua迭代
迭代 function enum(array) local index = 1 return function() --返回迭代函数 local ret = array[index] index = ...
- CSS vs. JS Animation: 哪个更快
CSS vs. JS Animation: 哪个更快? CSS vs. JS Animation: 哪个更快? 基于JavaScript的动画竟然已经默默地比CSS的transition动画快了?而且 ...
- Spring学习笔记之依赖的注解(2)
Spring学习笔记之依赖的注解(2) 1.0 注解,不能单独存在,是Java中的一种类型 1.1 写注解 1.2 注解反射 2.0 spring的注解 spring的 @Controller@Com ...
- 记一个男默女泪的 BUG
姗姗来迟的词频统计代码 BUG 的发现 1. 此前提交的第一次代码作业总结博客 http://www.cnblogs.com/ustczwq/p/8680704.html 2. BUG 本天成,妙手偶 ...
- 移动端H5 判断IOS还是Android 平台
1.方法 (function($) { var UA = window.navigator.userAgent; if(/Android|HTC/i.test(UA) || !!(window.nav ...