MySQL STRAIGHT_JOIN
问题
最近在调试一条查询耗时5s多的sql语句,这条sql语句用到了多表关联(inner join),按时间字段排序(order by),时间字段上已经创建了索引(索引名IDX_published_at)。通过explain分析发现,时间字段上的索引没用上(Using temporary和Using filesort),问题很明显,但是原因是什么呢?
SELECT * FROM news n0_ inner join news_translations n1_ ON n0_.id = n1_.translatable_id inner join channels_news c3_ ON n0_.id = c3_.news_id WHERE ((n0_.unpublished_at IS NOT NULL AND (CURRENT_TIMESTAMP >= n0_.published_at AND CURRENT_TIMESTAMP < n0_.unpublished_at)) OR (CURRENT_TIMESTAMP >= n0_.published_at AND n0_.unpublished_at IS NULL)) AND (n0_.status = 1 AND n0_.content_type_id = 1) AND n0_.id NOT IN (510466, 510433, 24, 11, 10, 9, 4) AND n0_.home_position_id IS NULL AND n1_.locale = 'zh_CN' AND c3_.channel_id = 1 ORDER BY n0_.published_at DESC LIMIT 5 ;
优化前sql语句
+-------+--------+-------------------------------+--------+-----------------------------------------------------------+ | table | type | key | rows | Extra | +-------+--------+-------------------------------+--------+-----------------------------------------------------------+ | c3_ | ref | IDX_87B9249E72F5A1AA | 161590 | Using where; Using index; Using temporary; Using filesort | | n0_ | eq_ref | PRIMARY | 1 | Using where | | n1_ | ref | UNIQ_20FDB3302C2AC5D34180C698 | 1 | Using where | +-------+--------+-------------------------------+--------+-----------------------------------------------------------+
explain分析结果 有所删减
经过一轮折腾的优化,得到了下面的sql语句
SELECT * FROM news n0_ STRAIGHT_JOIN news_translations n1_ ON n0_.id = n1_.translatable_id STRAIGHT_JOIN channels_news c3_ ON n0_.id = c3_.news_id WHERE ((n0_.unpublished_at IS NOT NULL AND (CURRENT_TIMESTAMP >= n0_.published_at AND CURRENT_TIMESTAMP < n0_.unpublished_at)) OR (CURRENT_TIMESTAMP >= n0_.published_at AND n0_.unpublished_at IS NULL)) AND (n0_.status = 1 AND n0_.content_type_id = 1) AND n0_.id NOT IN (510466, 510433, 24, 11, 10, 9, 4) AND n0_.home_position_id IS NULL AND n1_.locale = 'zh_CN' AND c3_.channel_id = 1 ORDER BY n0_.published_at DESC LIMIT 5 ;
优化后sql语句
+-------+--------+-------------------------------+--------+--------------------------+ | table | type | key | rows | Extra | +-------+--------+-------------------------------+--------+--------------------------+ | n0_ | range | IDX_published_at | 255440 | Using where | | n1_ | ref | UNIQ_20FDB3302C2AC5D34180C698 | 1 | Using where | | c3_ | eq_ref | PRIMARY | 1 | Using where; Using index | +-------+--------+-------------------------------+--------+--------------------------+
优化后explain分析结果 有所删减
优化前后的变化有四点:1、不再Using temporary和Using filesort;2、表的查询顺寻变了;3、查询扫描的rows增加了;4、查询时间由5s降到了0.02s。
原因分析
优化前后出现的四点变化,性能显著提升,需要从mysql的关联的连接处理说起。
以下参考《高性能MySQL》
1)优化前的sql语句以channels_news为第一个关联表,找到161590条记录;2)优化后的sql语句以news表为第一关联表,找到255440条记录,比第一条sql语句查找多了9W多条。因此,优化前的sql语句的关联顺序是MySQL优化器的选择,可以让查询进行更小的嵌套循环和回溯操作。MySQL通过选择合适的关联顺序来让查询执行的成本尽可能低,重新定义关联的顺序是优化器很重要的一部分功能。不过有时候,优化器给出的并不是最优的关联顺序。这时可以使用STRAIGHT_JOIN关键字重写查询,让优化器按照你认为的最优关联顺序执行。
从优化后的explain分析结果看出,news是驱动表,结果以news表的published_at字段进行排序,所以用上了索引,避免了Using temporary和Using filesort,自然而然的,查询时间也降下来了。正如前面说的,mysql的优化器通过粗暴的小表驱动大表来选择连接的顺序,第一条sql语句扫描了161590行,第二条sql语句扫描了255440行,优化后的sql语句扫描的行数增加了。
结语
结案陈词:造成这次sql语句查询耗时5s的原因是,sql语句order by的字段不在mysql的优化器选在驱动表上,所以导致这次关联查询排序字段上的索引没有被使用。因此,通过使用STRAIGHT_JOIN来强制制定关联查询的表顺序,以达到优化的目的。但是,有时候我们人为地指定顺序不一定比mysql的优化引擎准确,所以在使用STRAIGHT_JOIN的时候三思而后行。
本文链接:http://www.hcoding.com/?p=211
原创文章,转载请注明:JC&hcoding.com
书愤
陆游
早岁那知世事艰,中原北望气如山。
楼船夜雪瓜洲渡,铁马秋风大散关。
塞上长城空自许,镜中衰鬓已先斑。
出师一表真名世,千载谁堪伯仲间。
转载于:https://www.cnblogs.com/szuyuan/p/4273412.html
MySQL STRAIGHT_JOIN相关推荐
- mysql natural join_MySQL STRAIGHT_JOIN 与 NATURAL JOIN
MySQL STRAIGHT_JOIN STRAIGHT_JOIN 是 MySQL 对标准 SQL 的扩展,用于在多表查询时指定表载入的顺序.在 JOIN 表连接中,同样可以指定表载入的顺序,本文只讲 ...
- [转]Mysql Join语法解析与性能分析
转自:http://www.cnblogs.com/BeginMan/p/3754322.html 一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 ...
- mysql join性能_Mysql Join语法解析与性能分析
一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...
- 【MySQL】MySQL STRAIGHT JOIN 使用案例以及简介
1.概述 官方:MySQL STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the ...
- mysql join 性能测试_Mysql Join语法解析与性能分析
一.Join语法概述 join 用于多表中字段之间的联系,语法如下: SELECT * FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona t ...
- mysql中调用多个表_MySQL 多表查询
文章转载的:http://www.cnblogs.com/BeginMan/p/3754322.html 一.多表查询方法分类 1.交叉连接查询(得到的是两个表的乘积,类似于矩阵乘积) select ...
- Mysql常用语句帅哥特供版
[TOC] Mysql常用语句帅哥特供版 没错,这里的帅哥指的就是我自己 limit命令 查询 # limit命令 有两个参数, 第一个代表起始,从第几条开始. 第二个代表步长,取多少条. # 但是部 ...
- mysql多表关联left join_Mysql多表表关联查询 inner Join left join right join
一.Join语法概述 join 用于多表中字段之间的联系,语法如下:... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1: ...
- MySql-Join语法
一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...
最新文章
- Ribbon For WPF的使用
- leetcode 566. 重塑矩阵(Java版,坐标转换)
- 怎么让sql查询的字段可以不出现在group分组里_在工作中常用到的SQL
- 汇编常见寄存器以及标志位
- DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016,表挂起
- pyecharts绘制地铁图_安利一个绘制地铁线路KMZ的利器 号称国产谷歌地球
- 华为 博士 实习_华科女博士年薪156入职华为!最新回应:在深圳也难买房…
- 开课吧:AI智能语言产品会运用到哪些技术?
- 聊聊EurekaRibbonClientConfiguration
- dell 7040m 黑苹果_王者做图显示器,戴尔(DELL)U2417全面介绍
- 28、ZigBee 开发教程之基础篇—红外对射计数器
- 选择导入过滤器endnote_EndNote 知网的 Import Filter (滤件制作实例) | 科研动力
- 画外因 | 笛卡尔与瑞典女王在 “数学课”上谈人生
- 笔记本双系统linux显示屏显示错误(笔记本屏幕显示错误 | 外接显示屏显示错误)
- RocketMQ避坑指南:java后端开发电脑配置
- vs java_VSCode搭建Java开发运行环境
- 多个日期时间段进行合并计算时长,剔除重叠时间段
- oracle验证公民身份号码
- 山世光: 我的Face Zero之梦,写在AlphaGo Zero出世之际
- Python实践之用PySimpleGUI库开发可视化界面