PostgreSQL:存在vs左连接

时间:2010-06-24 14:16:24

标签: performance postgresql explain

我多次听到postgres处理存在查询的速度比 left join 更快。 http://archives.postgresql.org/pgsql-performance/2002-12/msg00185.php

对于一个表聚合来说,这肯定是正确的。

但在我们的案例中,他们的内容超过了一个,同样的查询构建存在,这使得postgres永远挂起:

explain 
SELECT count(DISTINCT "groups".id) AS count_all 
FROM "groups"
WHERE (exists(
    select * from products p where groups.id = p.group_id AND exists(
        select * from products_categories pc where p.id = pc.product_id AND pc.category_id in (2,3))) AND groups.id != 3) 

结果:

 Aggregate  (cost=26413436.66..26413436.67 rows=1 width=4)
   ->  Seq Scan on groups  (cost=0.00..26413403.84 rows=13126 width=4)
         Filter: ((id <> 3) AND (subplan))
         SubPlan
           ->  Index Scan using index_products_on_group_id on products p  (cost=0.00..1006.13 rows=1 width=1483)
                 Index Cond: ($1 = group_id)
                 Filter: (subplan)
                 SubPlan
                   ->  Seq Scan on products_categories pc  (cost=0.00..498.49 rows=1 width=8)
                         Filter: ((category_id = ANY ('{2,3}'::integer[])) AND ($0 = product_id))

这是执行时间极长的根本原因? 这是某种配置问题吗?

谢谢, 波格丹。

1 个答案:

答案 0 :(得分:1)

好吧,对于“groups”中的每一行,postgresql正在对products_categories进行全面扫描,这并不好。不一定是配置问题,但也许可以在没有嵌套子查询的情况下声明查询?

SELECT count(DISTINCT "groups".id) AS count_all 
FROM "groups"
WHERE exists(
    select 1 from products p where groups.id = p.group_id
             join products_categories pc on pc.product_id = p.id
    where pc.category_id in (2,3)
    ) and groups.id <> 3

products_categories还有product_id的索引吗?