使用OR子句查询的查询时间过长,但是它们的组成部分很快

时间:2018-08-27 16:26:22

标签: mysql sql database performance

我有两个表,其中的〜1M行由其ID索引。

休闲查询...

SELECT t.* FROM transactions t
INNER JOIN integration it ON it.id_trans = t.id_trans
WHERE t.id_trans = '5440073'
OR it.id_integration = '439580587'

此查询大约需要30秒。但是...

SELECT ... WHERE t.id_trans = '5440073'

花费不到100毫秒的时间,并且

SELECT ... WHERE it.id_integration = '439580587'

也花费不到100毫秒。偶

SELECT ... WHERE t.id_trans = '5440073'
UNION
SELECT ... WHERE it.id_integration = '439580587'

花费不到100毫秒

即使部分很快,OR子句为什么仍要花费很多时间?

2 个答案:

答案 0 :(得分:1)

为什么OR这么慢,但是UNION这么快?

您了解为什么UNION快吗?因为它可以使用两个单独的索引来发挥良好的优势,并从UNION的每个部分收集一些结果行,然后将结果组合在一起。

但是OR为什么不能这样做?简而言之,Optimizer不够聪明,无法尝试该角度。

在您的情况下,测试位于不同的表中;对于EXPLAIN SELECT ...的两个部分,这将导致根本不同的查询计划(请参见UNION)。每个都可以很好地优化,所以每个都很快。

假设每个部分仅传递几行,则UNION的后续开销很小-即收集两行小集,对它们进行重复处理(如果您使用UNION DISTINCT而不是{{ 1}}),并提供结果。

与此同时,UNION ALL查询可以有效地收集两个表的所有组合,然后根据OR的两个部分过滤出 then 。中间阶段可能涉及一个巨大的临时表,只是要扔掉大多数行。

(inflate-deflate的另一个示例是OR + JOINs。解决方法不同。)

答案 1 :(得分:0)

我建议使用http://编写查询:

UNION ALL

注意:如果id是真正的数字(而不是字符串),请删除单引号。混合类型有时会混淆优化器并阻止使用索引。