这是最近一次在工作中出现的情况。
考虑三个表,A,B,C。
A有3,000行;B有300,000,000行;C有2,000行。
定义了外键:B(a_id),B(c_id)。
假设您有一个查询,如下所示:
select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id
以我的经验,在这种情况下,MySQL可能会选择C-> B->A。C小于A,B巨大,它们都是等价的。
问题是MySQL不一定考虑(C.id和B.c_id)与(A.id和B.a_id)之间交集的大小。如果B和C之间的联接返回的行数与B一样多,那么这是一个非常糟糕的选择;如果以A开头将B过滤到与A一样多的行,那将是一个更好的选择。straight_join
可以用来强制执行以下命令:
select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id
现在a
必须先加入b
。
通常,您希望以最小化结果集中的行数的顺序进行连接。因此,从一个小表开始并进行连接以使生成的连接也较小,这是理想的选择。如果从一个小桌子开始,然后将其连接到一个更大的桌子上,那么事情就变成了梨形,而结果却和大桌子一样大。
虽然这取决于统计数据。如果数据分布发生变化,则计算可能会发生变化。它还取决于联接机制的实现细节。
对于MySQL,我看到的最糟糕的情况是,除了必需的straight_join
索引索引或主动索引索引索引外,其余所有查询都是按严格的排序顺序使用光过滤对大量数据进行分页的查询。MySQL强烈希望对任何过滤器使用索引,并且对排序进行联接。这是有道理的,因为大多数人不是在尝试对整个数据库进行排序,而是拥有有限的行子集来响应查询,并且对有限的子集进行排序比筛选整个表要快得多,无论是对表进行排序还是对表进行过滤不。在这种情况下,将直接连接放在要对固定内容进行排序的具有索引列的表之后。
straight_join
。