如何强制连接顺序以提高 MYSQL 中的查询性能?

Posted

技术标签:

【中文标题】如何强制连接顺序以提高 MYSQL 中的查询性能?【英文标题】:How to force the order of the joins to improve query performance in MYSQL? 【发布时间】:2020-06-11 16:51:09 【问题描述】:

我有一条sql语句

SELECT count(*)
From table1 
inner join table2 on condition1
..
inner join tableN on conditionN-1
inner join problematic_table on tableN.FKColumn= problematic_table.FKColumn

这会在 20-25 秒内产生结果。

如果我像这样运行查询,它会运行得更快。 100毫秒内

select count(*)
from problematic_table where problematic_table.FKColumn in (
select distinct tableN.FKColumn
    From table1 
    inner join table2 on condition1
    ..
    inner join tableN on conditionN-1
)

我想指出,从 table1 到 tableN 的表连接没有结果(为空)。

那么为什么第一种情况的性能那么差呢?

编辑: 运行 EXPLAIN 时,表的排序顺序与我在 JOIN 中编写的顺序不同

EDIT2 所以对于第一个查询,problemati_table 连接不是最后运行的,而是实际将行数减少到 0 的查询最后运行。 对于第二个查询是相同的顺序,除了有问题的_表在顶部 id=1 和 select_type=Primary,其他的是 id=2 和 select_type=MATERIALIZED。

所以我想问题变成了如何让引擎按照我写的顺序运行查询?

EDIT3

可能的情况是引擎最后运行的连接条件是 TABLE1 和 TABLE2,它们的形式为:

SELECT
FROM TABLE1
INNER JOIN TABLE2 on TABLE1.COLUMN1='constant_string' and TABLE2.COLUMN2='constant_string2'
INNER JOIN ... other tables have proper join conditions between colums of the tables.

EDIT4 更改了问题的标题以吸引可能面临相同问题的其他人。

【问题讨论】:

使用EXPLAIN 找出答案。 显示有效样本 .. 您在条件 1 上的内部连接表 2 太模糊,为了性能,您应该避免使用 IN 子句 条件重要吗?从 table1 到 tableN 的连接产生 0 个结果并且速度很快。为什么0结果内联表需要20秒? 你的问题太笼统了。它缺乏足够的细节来帮助您。表problematic_table 有哪些索引? “运行 EXPLAIN 时,表的排序顺序与我在 JOIN 中编写的顺序不同”——当然。 SQL 是一种声明性 语言,而不是一种命令性 语言。引擎将尽可能多地重写、改写、优化、清理查询,以使其便宜。它不会运行您编写的确切代码。 【参考方案1】:

问题是引擎运行连接的顺序很糟糕。 我通过使用STRAIGHT_JOIN 优化器提示而不是简单的INNER JOIN 解决了这个问题

【讨论】:

我不相信你。 STRAIGHT_JOIN 强制排序;它不会“修复优化器问题的基础问题”。而且,任何类似的提示都可能“今天有所帮助,但明天会有所伤害”(当数据集发生变化时)。 @Rick 这个案例符合“我知道它不会是这种情况”。请参阅我对这个问题的最后评论。

以上是关于如何强制连接顺序以提高 MYSQL 中的查询性能?的主要内容,如果未能解决你的问题,请参考以下文章

如何提高 Django 管理员搜索相关字段(MySQL)中的查询性能

如何提高MYSQL查询的性能?

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

优化 SQL:如何重写此查询以提高性能? (使用子查询,摆脱 GROUP BY?)

如何提高 SQL Server 查询的性能以选择具有值的行不在子查询中的一次计数

如何使用许多 JOIN 提高查询性能