所以,我有两张桌子:桌子A和桌子B。在对这些表进行简单的内部连接时,

SELECT *
FROM tableA
JOIN tableB
ON tableA.columnA = tableB.id

现在,tableA包含29000多行,而tableB仅包含11000多行。tableB.id是主键,因此是聚集键。在columnA上存在非聚集索引。
根据我的想法,查询优化器在执行联接时应该将tableB视为内部表,因为它的行数较少,而将tableA视为外部表,因为需要根据tableA列的值从tableB.id中筛选出许多行。
但是,事实恰恰相反。出于某种原因,查询优化器将tableA视为内部表,tableB视为外部表。
有人能解释一下为什么会这样,我在思考过程中犯了什么错误吗?此外,是否有办法强制取代查询优化器的决策,并要求它将tableB视为内部表?我只是想看看同一个查询的两个不同执行是如何相互比较的。谢谢。

最佳答案

在InnoDB中,主键索引查找的效率略高于辅助索引查找。优化器可能更喜欢运行对tableB.id进行查找的连接,因为它使用主键索引。
如果要重写优化器对表重新排序的能力,可以使用优化器提示。将按照您在查询中指定的顺序访问表。

SELECT *
FROM tableA
STRAIGHT_JOIN tableB
ON tableA.columnA = tableB.id

这种语法应该适用于任何当前支持的MySQL版本。
这将使您有机会对任意一个表顺序进行时间查询,并查看哪个表的运行速度更快。
MySQL 8.0中还有一个新的语法来指定具有更大控制的连接顺序:https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html#optimizer-hints-join-order

10-02 05:31
查看更多