问题

最近在调试一条查询耗时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相关推荐

  1. mysql natural join_MySQL STRAIGHT_JOIN 与 NATURAL JOIN

    MySQL STRAIGHT_JOIN STRAIGHT_JOIN 是 MySQL 对标准 SQL 的扩展,用于在多表查询时指定表载入的顺序.在 JOIN 表连接中,同样可以指定表载入的顺序,本文只讲 ...

  2. [转]Mysql Join语法解析与性能分析

    转自:http://www.cnblogs.com/BeginMan/p/3754322.html 一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 ...

  3. mysql join性能_Mysql Join语法解析与性能分析

    一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...

  4. 【MySQL】MySQL STRAIGHT JOIN 使用案例以及简介

    1.概述 官方:MySQL STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the ...

  5. mysql join 性能测试_Mysql Join语法解析与性能分析

    一.Join语法概述 join 用于多表中字段之间的联系,语法如下: SELECT * FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona t ...

  6. mysql中调用多个表_MySQL 多表查询

    文章转载的:http://www.cnblogs.com/BeginMan/p/3754322.html 一.多表查询方法分类 1.交叉连接查询(得到的是两个表的乘积,类似于矩阵乘积) select ...

  7. Mysql常用语句帅哥特供版

    [TOC] Mysql常用语句帅哥特供版 没错,这里的帅哥指的就是我自己 limit命令 查询 # limit命令 有两个参数, 第一个代表起始,从第几条开始. 第二个代表步长,取多少条. # 但是部 ...

  8. mysql多表关联left join_Mysql多表表关联查询 inner Join left join right join

    一.Join语法概述 join 用于多表中字段之间的联系,语法如下:... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1: ...

  9. MySql-Join语法

    一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...

最新文章

  1. Ribbon For WPF的使用
  2. leetcode 566. 重塑矩阵(Java版,坐标转换)
  3. 怎么让sql查询的字段可以不出现在group分组里_在工作中常用到的SQL
  4. 汇编常见寄存器以及标志位
  5. DB2 SQL Error: SQLCODE=-668, SQLSTATE=57016,表挂起
  6. pyecharts绘制地铁图_安利一个绘制地铁线路KMZ的利器 号称国产谷歌地球
  7. 华为 博士 实习_华科女博士年薪156入职华为!最新回应:在深圳也难买房…
  8. 开课吧:AI智能语言产品会运用到哪些技术?
  9. 聊聊EurekaRibbonClientConfiguration
  10. dell 7040m 黑苹果_王者做图显示器,戴尔(DELL)U2417全面介绍
  11. 28、ZigBee 开发教程之基础篇—红外对射计数器
  12. 选择导入过滤器endnote_EndNote 知网的 Import Filter (滤件制作实例) | 科研动力
  13. 画外因 | 笛卡尔与瑞典女王在 “数学课”上谈人生
  14. 笔记本双系统linux显示屏显示错误(笔记本屏幕显示错误 | 外接显示屏显示错误)
  15. RocketMQ避坑指南:java后端开发电脑配置
  16. vs java_VSCode搭建Java开发运行环境
  17. 多个日期时间段进行合并计算时长,剔除重叠时间段
  18. oracle验证公民身份号码
  19. 山世光: 我的Face Zero之梦,写在AlphaGo Zero出世之际
  20. Python实践之用PySimpleGUI库开发可视化界面

热门文章

  1. jieba库解析、统计《三国演义中》词出现的频度,找出频度最高的人物名
  2. RV1126笔记三十:freetype显示矢量字体
  3. Assert.assertEquals是什么含义
  4. java arraydeque poll,Java ArrayDeque
  5. 如何创建个人求职网站?
  6. 全球与中国混凝土整体颜料市场深度研究分析报告
  7. 不抱怨不解释--为了换一个吃饭的地方
  8. 记一次 ftp 可以正常登录,但是输入ls dir 命令卡死的问题
  9. Kafka学习之消费者
  10. Google Play的一款专业电子琴。ORG 2020 汉化版