查询使用IN表达式运行比使用OR查询慢

时间:2014-12-29 08:41:30

标签: postgresql

我有两个查询,一个是使用 OR 表达式并且运行速度非常快。另一个查询类似但是使用 IN 表达式而不是 OR 并且运行速度非常慢。如果您能够使用 IN 和使用 OR 一样快速地告诉我如何使用 IN ,我将不胜感激。该表有1500万条记录

SELECT e.id
FROM events e,
     resources r
WHERE e.resource_id = r.id
  AND resource_type_id IN (19872817,
                           282)
ORDER BY occurrence_date DESC LIMIT 100


Limit  (cost=0.85..228363.80 rows=100 width=12) (actual time=238.668..57470.017 rows=19 loops=1)
  ->  Nested Loop  (cost=0.85..26211499.28 rows=11478 width=12) (actual time=238.667..57470.010 rows=19 loops=1)
        Join Filter: (e.resource_id = r.id)
        Rows Removed by Join Filter: 507548495
        ->  Index Scan using eventoccurrencedateindex on events e  (cost=0.43..603333.83 rows=15380258 width=16) (actual time=0.023..2798.538 rows=15380258 loops=1)
        ->  Materialize  (cost=0.42..36.16 rows=111 width=4) (actual time=0.000..0.001 rows=33 loops=15380258)
              ->  Index Scan using resources_type_fk_index on resources r  (cost=0.42..35.60 rows=111 width=4) (actual time=0.014..0.107 rows=33 loops=1)
                    Index Cond: (resource_type_id = ANY ('{19872817,282}'::integer[]))
Total runtime: 57470.057 ms


SELECT e.id
FROM events e,
     resources r
WHERE e.resource_id = r.id
    AND (resource_type_id = '19872817' OR resource_type_id = '282')
ORDER BY occurrence_date DESC LIMIT 100


Limit  (cost=10.17..14.22 rows=100 width=12) (actual time=0.060..0.181 rows=100 loops=1)
  ->  Nested Loop  (cost=10.17..34747856.23 rows=858030913 width=12) (actual time=0.059..0.167 rows=100 loops=1)

  Join Filter: (((e.resource_id = r.id) AND (r.resource_type_id = 19872817)) OR (r.resource_type_id = 282))

  ->  Index Scan using eventoccurrencedateindex on events e  (cost=0.43..603333.83 rows=15380258 width=16) (actual time=0.018..0.019 rows=4 loops=1)

  ->  Materialize  (cost=9.74..349.92 rows=111 width=8) (actual time=0.009..0.023 rows=25 
loops=4)

  ->  Bitmap Heap Scan on resources r  (cost=9.74..349.36 rows=111 width=8) (actual time=0.034..0.081 rows=33 loops=1)
  Recheck Cond: ((resource_type_id = 19872817) OR (resource_type_id = 282))

  ->  BitmapOr  (cost=9.74..9.74 rows=111 width=0) (actual time=0.023..0.023 rows=0 loops=1)

  ->  Bitmap Index Scan on resources_type_fk_index  (cost=0.00..4.84 rows=56 width=0) (actual time=0.009..0.009 rows=0 loops=1)
  Index Cond: (resource_type_id = 19872817)

  ->  Bitmap Index Scan on resources_type_fk_index  (cost=0.00..4.84 rows=56 width=0) (actual time=0.014..0.014 rows=33 loops=1)
  Index Cond: (resource_type_id = 282)" "Total runtime: 0.242 ms

1 个答案:

答案 0 :(得分:1)

这在or版本中很奇怪:

Join Filter: (
    ((e.resource_id = r.id) AND (r.resource_type_id = 19872817)) 
    OR 
    (r.resource_type_id = 282)
)

首先e.resource_id = r.id AND r.resource_type_id = 19872817然后OR r.resource_type_id = 282这是错误的。您确定在该查询中发出了正确的条件吗?请注意,必须有括号OR

e.resource_id = r.id 
AND 
(r.resource_type_id = 19872817 OR r.resource_type_id = 282)