query使用or子句进行查询花费的时间太长,但是它们的部分非常快

slwdgvem  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(273)

我有两个表,其中约1百万行按其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 即使零件这么快也要花这么多时间?

plupiseo

plupiseo1#

为什么是 OR 太慢了,但是 UNION 这么快?
你明白为什么吗 UNION 速度快吗?因为它可以很好地使用两个单独的索引,并从每个部分收集一些结果行 UNION ,然后将结果合并在一起。
但为什么不能呢 OR 你这么做?简单地说,优化器不够聪明,无法尝试这个Angular 。
在您的情况下,测试在不同的表上;这将导致完全不同的查询计划(参见 EXPLAIN SELECT ... )对于这两部分 UNION . 每个都可以很好地优化,所以每个都很快。
假设每个部分只传递几行,则 UNION 是次要的——即收集两个小的行集,对它们进行重复数据消除(如果使用 UNION DISTINCT 而不是 UNION ALL ),并交付结果。
与此同时 OR 查询有效地收集了两个表的所有组合,然后根据表的两个部分进行过滤 OR . 中间阶段可能涉及一个巨大的temp表,只会抛出大部分行。
(充气-放气的另一个例子是 JOINs + GROUP BY . 解决方法不同。)

z9ju0rcb

z9ju0rcb2#

我建议使用 UNION ALL :

SELECT t.*
FROM transactions t
WHERE t.id_trans = '5440073'
UNION ALL
SELECT t.*
FROM transactions t JOIN
     integration it 
     ON it.id_trans = t.id_trans
WHERE t.id_trans <> '5440073' AND
      it.id_integration = '439580587';

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

相关问题