Postgres Materialize导致删除查询性能不佳

时间:2014-10-21 00:58:37

标签: database postgresql query-performance materialized-views sql-delete

我有一个DELETE查询,我需要在PostgreSQL 9.0.4上运行。我发现它是高性能的,直到它在subselect查询中遇到524,289行。

例如,在524,288,没有使用物化视图,成本看起来很不错:

explain DELETE FROM table1 WHERE pointLevel = 0 AND userID NOT IN
(SELECT userID FROM table2 fetch first 524288 rows only);
                                                QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Delete  (cost=13549.49..17840.67 rows=21 width=6)
   ->  Index Scan using jslps_userid_nopt on table1  (cost=13549.49..17840.67 rows=21 width=6)
         Filter: ((NOT (hashed SubPlan 1)) AND (pointlevel = 0))
         SubPlan 1
           ->  Limit  (cost=0.00..12238.77 rows=524288 width=8)
                 ->  Seq Scan on table2  (cost=0.00..17677.92 rows=757292 width=8)
(6 rows)

然而,只要我达到524,289,物化视图就会发挥作用,DELETE查询会变得更加昂贵:

explain DELETE FROM table1 WHERE pointLevel = 0 AND userID NOT IN
(SELECT userID FROM table2 fetch first 524289 rows only);

  QUERY PLAN

-----------------------------------------------------------------------------------------------------------  
Delete  (cost=0.00..386910.33 rows=21 width=6)
    ->  Index Scan using jslps_userid_nopt on table1  (cost=0.00..386910.33 rows=21 width=6)
         Filter: ((pointlevel = 0) AND (NOT (SubPlan 1)))
         SubPlan 1
           ->  Materialize  (cost=0.00..16909.24 rows=524289 width=8)
                 ->  Limit  (cost=0.00..12238.79 rows=524289 width=8)
                       ->  Seq Scan on table2  (cost=0.00..17677.92 rows=757292 width=8) (7 rows)

我通过在子选择查询中使用JOIN来解决这个问题:

SELECT s.userid 
FROM table1 s 
LEFT JOIN table2 p ON s.userid=p.userid
WHERE p.userid IS NULL AND s.pointlevel=0

但是,我仍然有兴趣了解为什么物化会如此大幅度地降低性能。

1 个答案:

答案 0 :(得分:6)

我的猜测是,在rows=524289内存缓冲区被填满,因此子查询必须在磁盘上实现。因此,所需时间急剧增加。

在这里,您可以阅读有关配置内存缓冲区的更多信息:http://www.postgresql.org/docs/9.1/static/runtime-config-resource.html
如果您使用work_mem,则会看到查询行为的差异。

但是,在子查询中使用join是加快查询速度的更好方法,因为您要限制源本身的行数,而不是简单地选择第一个XYZ行然后执行检查。