mysql - 如何强制更改内部连接的评估顺序?

Posted

技术标签:

【中文标题】mysql - 如何强制更改内部连接的评估顺序?【英文标题】:mysql - How to forcefully change the order of evaluation of an inner join? 【发布时间】:2018-12-17 19:55:12 【问题描述】:

所以,我有这两个表:tableA 和 tableB。在对这些表进行简单的内部连接后,

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

现在,tableA 包含 29000+ 行,而 tableB 仅包含 11000+ 行。 tableB.id 是主键,因此是聚集的。 columnA 上存在一个非聚集索引。

根据我的想法,查询优化器在执行连接时应该将tableB视为内表,因为它的行数较少,而将tableA视为外表,因为很多行需要根据tableB.id 列的值从tableA 中过滤。

但是,事实恰恰相反。出于某种原因,查询优化器将tableA 视为内部表,将tableB 视为外部表。

谁能解释一下为什么会发生这种情况以及我在思考过程中犯了什么错误?此外,有没有办法强制取代查询优化器的决定并指示将tableB 视为内表?我只是想知道同一查询的两个不同执行如何相互比较。谢谢。

【问题讨论】:

请注意,内部联接中没有“内部”表,内部描述了正在建立的联接类型。 您应该考虑服务器对这些表中数据的索引统计。在某些情况下,如果根据统计信息这样做没有意义,服务器可能会决定根本不使用索引。 请对minimal reproducible example采取行动,包括提供 DDL 和 EXPLAIN 输出。阅读 mysql 手册重新索引和优化中的所有内容,包括 statistics。当您使用 STRAIGHT JOIN 以两种方式运行查询时发生了什么? PS“我在思考过程中犯的错误”是认为一个不知情的猜测是相关的。要开始了解自己,请阅读您正在使用的每个功能的精美手册。那么你用 site:Stack Overflow & with site:Database Administrators 谷歌搜索告诉你什么?请参阅How to Ask 和投票箭头鼠标悬停文本。 Is there a way to force MySQL execution order?的可能重复 【参考方案1】:

在 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

【讨论】:

以上是关于mysql - 如何强制更改内部连接的评估顺序?的主要内容,如果未能解决你的问题,请参考以下文章

如何强制 Access 更改无 DSN 的 ODBC 连接的用户名和密码?

如何为 iTunes 连接提供强制更新?

在 MySQL 中强制使用索引进行连接的语法是啥

如何修复`EF Core中的远程主机`错误强制关闭现有连接

MySQL JOIN 的评估顺序是啥?

有没有办法强制 Oracle 在加入访问后评估过滤器?