Postgres没有索引只扫描删除?

时间:2015-09-25 18:02:33

标签: postgresql

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

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

                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 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)
(4 rows)

这是实际的删除查询SQL。这不是,但我确信应该使用与上面相同的Index Only Scan,我想知道它是否是Postgres中的一个错误?注意成本较高:

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)

我在其他例子中注意到了这种行为。所以任何人都有任何想法?

0 个答案:

没有答案