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