Postgresql Postgres无索引只在删除时扫描?

Postgresql Postgres无索引只在删除时扫描?,postgresql,Postgresql,我在Postgres 9.3.9中运行了一个查询,我想使用与我创建的特定部分索引条件匹配的EXISTS子句从临时表中删除一些记录。以下相关查询在此部分索引上使用仅索引扫描(以下缩写为“条件”): 下面是实际的删除查询SQL。这并没有,但我确信应该使用与上面相同的索引扫描,我想知道这是否是Postgres中的一个bug?请注意较高的成本: DELETE FROM temp_table l WHERE EXISTS(SELECT 1 FROM cnu.customers

我在Postgres 9.3.9中运行了一个查询,我想使用与我创建的特定部分索引条件匹配的EXISTS子句从临时表中删除一些记录。以下相关查询在此部分索引上使用仅索引扫描(以下缩写为“条件”):

下面是实际的删除查询SQL。这并没有,但我确信应该使用与上面相同的索引扫描,我想知道这是否是Postgres中的一个bug?请注意较高的成本:

DELETE
  FROM temp_table l
  WHERE EXISTS(SELECT 1
          FROM cnu.customers cx
          WHERE cx.id = l.customer_id
            AND ( conditions ));


                                           QUERY PLAN                                           
------------------------------------------------------------------------------------------------
 Delete on temp_table l  (cost=0.42..495426.94 rows=43549 width=12)
   ->  Nested Loop Semi Join  (cost=0.42..495426.94 rows=43549 width=12)
         ->  Seq Scan on temp_table l  (cost=0.00..1277.98 rows=87098 width=10)
         ->  Index Scan using customers__bad on customers cx  (cost=0.42..6.67 rows=1 width=10)
               Index Cond: (id = l.customer_id)
(5 rows)
为了证明删除时可以获得相同的计划,我必须这样做,它给了我想要的计划,速度是上面使用索引扫描而不是仅索引扫描的查询的两倍:

WITH the_right_records AS
(SELECT l.id
FROM temp_table l
WHERE NOT EXISTS
        (SELECT 1
          FROM cnu.customers cx
          WHERE cx.id = l.customer_id
            AND ( conditions ))

DELETE FROM temp_table t
WHERE NOT EXISTS (SELECT 1
                  FROM the_right_records x
                  WHERE x.id = t.id);

                                              QUERY PLAN                                              
------------------------------------------------------------------------------------------------------
 Delete on temp_table t  (cost=253855.72..256902.88 rows=43549 width=34)
   CTE the_right_records
     ->  Nested Loop Anti Join  (cost=0.42..252440.38 rows=43549 width=4)
           ->  Seq Scan on temp_table l  (cost=0.00..1277.98 rows=87098 width=8)
           ->  Index Only Scan using customers__bad on customers cx  (cost=0.42..3.35 rows=1 width=4)
                 Index Cond: (id = l.customer_id)
   ->  Hash Anti Join  (cost=1415.34..4462.50 rows=43549 width=34)
         Hash Cond: (t.id = x.id)
         ->  Seq Scan on temp_table t  (cost=0.00..1277.98 rows=87098 width=10)
         ->  Hash  (cost=870.98..870.98 rows=43549 width=32)
               ->  CTE Scan on the_right_records x  (cost=0.00..870.98     rows=43549 width=32)
(11 rows)

我在其他例子中也注意到了同样的行为。有人有什么想法吗?

快速浏览一下:您的第二个查询(不使用仅索引扫描的查询)显示“WHERE EXISTS”,而您的所有其他查询显示“WHERE NOT EXISTS”。相同的逻辑虽然
选择WHERE NOT EXISTS
应该与
删除WHERE EXISTS
相同。可能是相同的逻辑,但不同的统计数据。“swans是黑色的”与“swans不是黑色的”可能值得作为一个可能的计划问题来提高pgsql性能
WITH the_right_records AS
(SELECT l.id
FROM temp_table l
WHERE NOT EXISTS
        (SELECT 1
          FROM cnu.customers cx
          WHERE cx.id = l.customer_id
            AND ( conditions ))

DELETE FROM temp_table t
WHERE NOT EXISTS (SELECT 1
                  FROM the_right_records x
                  WHERE x.id = t.id);

                                              QUERY PLAN                                              
------------------------------------------------------------------------------------------------------
 Delete on temp_table t  (cost=253855.72..256902.88 rows=43549 width=34)
   CTE the_right_records
     ->  Nested Loop Anti Join  (cost=0.42..252440.38 rows=43549 width=4)
           ->  Seq Scan on temp_table l  (cost=0.00..1277.98 rows=87098 width=8)
           ->  Index Only Scan using customers__bad on customers cx  (cost=0.42..3.35 rows=1 width=4)
                 Index Cond: (id = l.customer_id)
   ->  Hash Anti Join  (cost=1415.34..4462.50 rows=43549 width=34)
         Hash Cond: (t.id = x.id)
         ->  Seq Scan on temp_table t  (cost=0.00..1277.98 rows=87098 width=10)
         ->  Hash  (cost=870.98..870.98 rows=43549 width=32)
               ->  CTE Scan on the_right_records x  (cost=0.00..870.98     rows=43549 width=32)
(11 rows)