当前位置: 首页 > 知识库问答 >
问题:

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

孙书
2023-03-14

我需要在PostgreSQL 9.0.4上运行一个删除查询。我发现它一直在运行,直到在子选择查询中达到524289行。

例如,524288没有使用物化视图,成本看起来相当不错:

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)

然而,当我点击524289时,物化视图就开始发挥作用,删除查询的成本就要高得多:

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

然而,我仍然有兴趣理解为什么materialize会大幅降低性能。

共有1个答案

卫高谊
2023-03-14

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

在这里,您可以阅读有关配置内存缓冲区的更多信息:http://www.postgresql.org/docs/9.1/static/runtime-config-resource.html
如果你玩work\u mem,你会看到查询行为的不同。

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

 类似资料:
  • 我正在尝试删除实体,但未生成删除查询,并且控制台中没有显示错误: 注意:@Transactional来自springFramework包 编辑: 我的所有配置都是正常的,因为我已经有了merge和persist函数,没有任何问题,只是remove方法不生成任何sql查询,也不删除给定的实体。 编辑2: 我是这样获得entityManager的:

  • 问题内容: 当我尝试从数据库中删除条目时,使用 然后我可以执行以下操作: 1)如果该行存在于数据库中,则将执行两个SQL查询:一个选择,然后一个删除 2)如果数据库中不存在该行,则仅执行选择查询 但是同样,更新不是这种情况。无论是否存在数据库行,都只会执行更新查询。 请让我知道为什么这种行为用于删除操作。这不是性能问题,因为遇到了两个查询而不是一个查询? 编辑: 我正在使用hibernate3.2

  • 以下示例将演示如何使用Delte查询,在DBUtils的帮助下删除记录。 我们将删除表中的一条记录。 语法 其中, deleteQuery − 删除包含占位符的查询。 queryRunner − 对象删除数据库中的员工对象。 为了理解上述与DBUtils相关的概念,我们编写一个将运行更新查询的示例。创建一个示例应用程序。 更新在DBUtils入门应用中创建的文件。 编译并运行应用程序,如下所述。

  • 问题内容: 我在SQL Server 2008 R2中有一个表,该表包含约400行(几乎没有任何内容)-它在主键(这是一个标识)上具有聚集索引。其他约13个表通过引用完整性(没有级联删除或更新)引用了该表。 插入/更新/获取几乎是即时的-我们正在谈论一瞬间(这应该在意料之中)。但是,使用PK进行删除最多需要3分钟,而我从未见过比1.5分钟更快的时间: 该指数非常分散-90%。我重建并重新组织了该索

  • 问题内容: 当我尝试从数据库中删除条目时,使用 然后我可以执行以下操作: 1)如果该行存在于数据库中,则将执行两个SQL查询:一个选择,然后一个删除 2)如果数据库中不存在该行,则仅执行选择查询 但是同样,更新不是这种情况。无论是否存在数据库行,都只会执行更新查询。 请让我知道为什么这种行为用于删除操作。这不是性能问题,因为遇到了两个查询而不是一个查询? 编辑: 我正在使用休眠3.2.5 样例代码

  • 问题内容: 我试图使用没有结果的过滤查询删除一些子行: 我得到了错误。 全栈跟踪: 我无法找到问题所在。 任何想法? 问候 问题答案: 在查找您的异常发生的源之后,我建议尝试以下操作: 请参阅delete方法的文档以了解其含义。传递参数将基本上运行查询两次,一次为选择,一次为删除。 如果运行两个查询是不希望的,通过代替,然后调用立即删除后,以避免不一致的状态的内部存储。