问题

这是很容易发现的问题通过SQL显示完整列表语句,如下:


选择邮政。
从后
内部联接post.id = post_tag.post_id post_tag
在post.status = 1和post_tag.tag_id = 123
通过post.created倒序
限制100




解释:因为邮政标签是多对多,有一个关联表post_tag。

尝试用解释查询SQL执行计划(长度有限,结果被删除):


+ + + + ---------- --------- ------- ----------------------------- +
表的关键字排| | | |额外|
+ + + + ---------- --------- ------- ----------------------------- +
| post_tag | tag_id | 71220 |使用;使用filesort |
|后|初级| 1 |使用|
+ + + + ---------- --------- ------- ----------------------------- +




以下是优化的SQL语句,而唯一不变的是改变连接straight_join :


选择邮政。
从后
straight_join post_tag在post.id = post_tag.post_id
在post.status = 1和post_tag.tag_id = 123
通过post.created倒序
限制100




尝试用解释查询SQL执行计划(长度有限,结果被删除):


+ + + + ---------- ---------------- -------- ------------- +
表的关键字排| | | |额外|
+ + + + ---------- ---------------- -------- ------------- +
|后| status_created | 119340 |使用|
| post_tag | post_id | 1 |使用|
+ + + + ---------- ---------------- -------- ------------- +




比较两个结果解释之前和之后的优化,优化的SQL大于行,但没有用filesort,性能提高。

解释

对于第一个SQL,为什么MySQL优化器选择了一个耗时的执行方案二SQL,你为什么提高改变连接straight_join后的表现吗

这一切都是从mysql的多表处理连接开始的,首先要确定谁是驱动表,也就是说以哪个表作为基准,在处理这类问题时,采用mysql优化器来解决简单而粗糙的方法:哪个表结果集是小的,其中表是驱动表。通常这是最好的选择。

说明:在解释结果中,第一行的表是驱动程序表。

继续后连接到post_tag例,MySQL的优化器有以下两个选项,这是:

使用后作为驱动表和过滤通过status_created指数,结果是119340线
使用post_tag作为驱动表,透过tag_id指数,结果是71220线


显然,post_tag过滤结果集较小,所以MySQL优化器选择了它作为驱动表,悲催的是我们需要在后表创建字段排序,不在传动领域的分类表,然后用filesort 不可避免的出现

当你知道它将要做什么时,就很容易优化它。首先,要确保排序字段在驱动表中。所以文章必须驱动表,所以straight_join 是答案,这迫使连接顺序。

…

但我一直认为,straight_join这种非标准的语法范畴不属于奇技淫巧,不尽可能,毕竟,在大多数情况下,MySQL的优化器可以做出正确的选择。