我有以下MySql查询:
select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1
运行大约需要30秒,这很奇怪,因为如果我注释掉join或where子句,则需要不到一秒的时间: 即。
select t1.*
from Table1 t1
where t1.FilterID = 1
或
select t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
每次不到一秒钟。
然后是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
并且查询在不到一秒的时间内执行。
更奇怪的是,我可以写:
select STRAIGHT_JOIN t1.*
from Table1 t1
inner join Table2 t2
on t1.CommonID = t2.CommonID
where t1.FilterID = 1
并且只需不到一秒钟,这种语法似乎不合法。
我猜第二个例子意味着只要写入INNER JOIN就会使用STRAIGHT_JOIN,但我找不到任何关于它的文档。
这里发生了什么,以及“加入优化器”如何导致这种相对较差的性能?我应该一直使用STRAIGHT_JOIN吗?我怎么知道何时使用它?
Table1和Table2都有整数主键; FilterID是另一个表的外键; CommonID列是第三个表的外键。他们都有索引。数据库引擎是InnoDB。
由于
答案 0 :(得分:40)
这里发生了什么,以及“加入优化器”如何导致这种相对较差的性能?
STRAIGHT_JOIN
强制执行表的连接顺序,因此在外循环中扫描table1
,在内循环中扫描table2
。
优化器并不完美(虽然相当不错),最可能的原因是过时的统计数据。
我应该始终使用
STRAIGHT_JOIN
不,只有当优化器出错时。这可能是您的数据分布严重偏差或无法正确计算(例如,对于空间或全文索引)。
我怎么知道何时使用它?
您应该收集统计数据,为这两种方式制定计划,并了解这些计划的含义。
如果你看到:
自动生成的计划不是最优的,无法通过标准方式进行改进,
STRAIGHT_JOIN
版本更好,您了解它始终会理解为什么总是会
,然后使用STRAIGHT_JOIN
。