最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

在MySQL中使用STRAIGHT_JOIN的教程

来源:懂视网 责编:小采 时间:2020-11-09 20:57:45
文档

在MySQL中使用STRAIGHT_JOIN的教程

在MySQL中使用STRAIGHT_JOIN的教程:问题 通过「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 = 1
推荐度:
导读在MySQL中使用STRAIGHT_JOIN的教程:问题 通过「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 = 1

问题

   通过「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」,综合来看,性能依然得到了提升。
解释

   对第一条SQL而言,为什么MySQL优化器选择了一个耗时的执行方案?对第二条SQL而言,为什么把连接方式改成STRAIGHT_JOIN之后就提升了性能?

   这一切还得从MySQL对多表连接的处理方式说起,首先要确定以谁为驱动表,也就是说以哪个表为基准,在处理此类问题时,MySQL优化器采用了简单粗暴的解决方法:哪个表的结果集小,就以哪个表为驱动表,通常这都是最佳选择。

   说明:在EXPLAIN结果中,第一行出现的表就是驱动表。

   继续post连接post_tag的例子,MySQL优化器有如下两个选择,分别是:

  1.     以post为驱动表,通过status_created索引过滤,结果集119340行
  2.     以post_tag为驱动表,通过tag_id索引过滤,结果集71220行

       显而易见,post_tag过滤的结果集更小,所以MySQL优化器选择它作为驱动表,可悲催的是我们还需要以post表中的created字段来排序,也就是说排序字段不在驱动表里,于是乎不可避免的出现了「Using filesort」,从而导致慢查询。

       知道了来龙去脉,优化起来就容易了。头等大事是务必保证排序字段在驱动表中,所以必须以post是驱动表,于是乎「STRAIGHT_JOIN」就成了答案,它强制了连接顺序。

       …

       不过我总觉得「STRAIGHT_JOIN」这种非标准的语法属于奇技淫巧的范畴,能不用尽量不用,毕竟多数情况下,MySQL优化器都能做出正确的选择。

您可能感兴趣的文章:

  • MySQL在右表数据不唯一的情况下使用left join的方法
  • MySQL中union和join语句使用区别的辨析教程
  • 在MySQL中使用JOIN语句进行连接操作的详细教程
  • MySQL中视图的使用及多表INNER JOIN的技巧分享
  • MYSQL使用inner join 进行 查询/删除/修改示例
  • 解析mysql left( right ) join使用on与where筛选的差异
  • 深入理解mysql之left join 使用详解
  • Mysql中Join的使用实例详解
  • 声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文档

    在MySQL中使用STRAIGHT_JOIN的教程

    在MySQL中使用STRAIGHT_JOIN的教程:问题 通过「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 = 1
    推荐度:
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top