为什么STRAIGHT_JOIN如此大幅度地改进了这个查询,以及在SELECT关键字之后编写它意味着什么?

zod*_*zod 53 mysql join

我有以下MySql查询:

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1
Run Code Online (Sandbox Code Playgroud)

运行大约需要30秒,这很奇怪,因为如果我注释掉连接或where子句,它需要不到一秒钟:即

select t1.*
from Table1 t1
where t1.FilterID = 1
Run Code Online (Sandbox Code Playgroud)

要么

select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
Run Code Online (Sandbox Code Playgroud)

每个不到一秒钟.

然后是STRAIGHT_JOIN关键字,我可以在这里找到一个参考:http: //dev.mysql.com/doc/refman/5.0/en/join.html

STRAIGHT_JOIN类似于JOIN,只是左表始终在右表之前读取.这可以用于连接优化器以错误顺序放置表的那些(少数)情况.

什么?我可以写:

select t1.*
from Table1 t1
STRAIGHT_JOIN  Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1
Run Code Online (Sandbox Code Playgroud)

并且查询在不到一秒的时间内执行.

更奇怪的是,我可以写:

select STRAIGHT_JOIN  t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1
Run Code Online (Sandbox Code Playgroud)

它只需不到一秒钟,这种语法似乎不合法.

我猜第二个例子意味着只要写入INNER JOIN就会使用STRAIGHT_JOIN,但我找不到任何关于它的文档.

这里发生了什么,以及"加入优化器"如何导致这种相对较差的性能?我应该一直使用STRAIGHT_JOIN吗?我怎么知道何时使用它?

Table1和Table2都有整数主键; FilterID是另一个表的外键; CommonID​​列是第三个表的外键.他们都有索引.数据库引擎是InnoDB.

谢谢

Qua*_*noi 43

这里发生了什么,以及"加入优化器"如何导致这种相对较差的性能?

STRAIGHT_JOIN强制表的连接顺序,因此table1在外循环和table2内循环中扫描.

优化器并不完美(虽然相当不错),最可能的原因是过时的统计数据.

我应该经常使用吗? STRAIGHT_JOIN

不,只有当优化器出错时.这可能是您的数据分布严重偏差或无法正确计算(例如,对于空间或全文索引).

我怎么知道何时使用它?

您应该收集统计数据,为两种方式构建计划并了解这些计划的含义.

如果你看到:

  1. 自动生成的计划不是最优的,无法通过标准方式进行改进,

  2. STRAIGHT_JOIN版本更好,你了解它总是会和理解,为什么它总是会

,然后使用STRAIGHT_JOIN.

  • @zod:你可以用这种方式写一个`STRAIGHT_JOIN`而不是每对表之间的单个`STRAIGHT_JOIN`.它使表按照在查询中写入的顺序加入. (3认同)
  • 谢谢.任何想法语法选择STRAIGHT_JOIN t1.*...吗? (2认同)
  • @Pacerier:来自docs:*`STRAIGHT_JOIN`强制优化器按照它们在`FROM`子句中列出的顺序连接表.如果优化程序以非最佳顺序连接表,则可以使用此方法加速查询.`STRAIGHT_JOIN`也可用于`table_references`列表.*http://dev.mysql.com/doc/refman/5.6/en/select.html (2认同)