所以,我有两个表: tableA和tableB。在对这些表进行简单的内连接时,
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视为内部表?我只是好奇地想知道同一查询的两种不同执行如何相互比较。谢谢。
发布于 2018-12-18 04:16:42
在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
https://stackoverflow.com/questions/53822147
复制相似问题