最近没怎么搞SQL优化,碰巧数据库被慢查询搞挂了,于是拿来练练手。

问题

通过「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优化器都能做出正确的选择。

stright 在mysql_MySQL优化的奇技淫巧之STRAIGHT_JOIN相关推荐

  1. jmr连接mysql_MYSQL 优化之延迟关联

    SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id 覆盖 索引 必须 要 存 ...

  2. bit索引 mysql_Mysql优化之索引实现原理

    什么是索引 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的 ...

  3. show status 优化mysql_mysql优化--show status

    show status:了解各种SQL的执行频率. 格式:show [session | global] status; session表示当前连接(默认),global表示自数据库启动至今. sho ...

  4. [慢查优化]联表查询注意谁是驱动表 你搞不清楚谁join谁更好时请放手让mysql自行判定...

    写在前面的话: 不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程: 不要求每个人一定知道线上(现在或未来)哪张表数据量大,哪张表数据量小: ...

  5. MySQL多表联查sql优化

    一.概述 from和join均是用于指定需要从哪些表查询数据,from可以是一个表或多个表,如果是多个表则是生成一个笛卡尔集,会涉及到大量数据.所以通常在涉及到多个表的查询时,通常通过join来拼接多 ...

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

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

  7. 海量之道之弱联网优化

    前言 [弱联网优化]作为海量之道2.0系列课题的基础方法论之一,望文生义,想必定是卖弄移动网络信号不佳时如何优化的奇技淫巧.恭喜你,感觉靠谱,不过我们还想多聊一点其它话题. 移动互联网颠覆着我们的生活 ...

  8. 一个深度学习痴呆选手对AlexNet网络架构的一些理解

    最近开始入坑深度学习,之前根本没接触过关于AI领域的知识,也就对着B站上的CS231N课水了水,但完全就是半懂不懂很懵逼的感觉,毕竟神经网络就类似于一个黑箱,难以理解也是很正常的.现在打算写一篇关于极 ...

  9. 澄清 | snappy压缩到底支持不支持split? 为啥?

    前两天,群里小伙伴问了一个问题: 不是说snappy压缩不支持split嘛,为什么我改小mapred.max.split.size一倍之后,mapper数翻倍? 一直以来大家都知道snappy是不支持 ...

最新文章

  1. python 可视化界面_工具推荐 | 3维数据可视化
  2. python书籍_python书籍购买建议
  3. Java开发面试问题,Jsoup解析html
  4. cylance做的机器学习相关材料汇总
  5. The Complete List of MIME Types
  6. EF 6 code first - 从SQL server迁移到MySQL
  7. 怎么在Windows11上禁用文件资源管理器搜索历史记录
  8. 一文说清Elasticsearch的核心概念
  9. VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结...
  10. linux 删除中文文件夹,Linux删除文件夹命令是什么
  11. 移动端布局,C3新增属性
  12. AMD OpenCL大学课程(13) OpenCL扩展
  13. JAVA酒店管理系统
  14. 16.2.4 登录到 SMTP 服务器
  15. teamtalk mysql.h_TeamTalk安装测试
  16. Open api qps request limit reached
  17. 《前端跨界开发指南》重磅来袭!
  18. 如何在Win10(包括2004版本)下安装64位CATIA
  19. HTML5特性之谷歌浏览器桌面消息(window.Notification)推送:
  20. Openwrt chaos_calmer 版本在Ubuntu18上编译问题汇总

热门文章

  1. XI 安装MS SQLSERVER JDBC 驱动
  2. 部署App-V Client,应用程序虚拟化体验系列之三
  3. 填写实验计算机桌面的系统图标有,Win8系统桌面添加计算机图标的图文步骤
  4. 用html5做一条线,使用HTML5 canvas绘制线条的方法
  5. laravel 定时任务
  6. OOD面向对象设计浅谈
  7. 茶百科 android 论文,基于android平台手机茶百科开发_学位论文.doc
  8. 后端需要掌握的技术_何小伟:软件测试需要掌握的技术?
  9. python bottle框架 重定向_Python的web框架bottle静态文件的路径
  10. linux io 分析,Linux 下的I/O性能分析 iotop