小编May*_*tel的帖子

Postgres 8.4.4(Win7 x64上的x32)在小表上非常慢的UPDATE

我有一个非常简单的更新声明:

UPDATE W SET state='thing'
WHERE state NOT IN ('this','that') AND losttime < CURRENT_TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)

表W只有90行,尽管每行大约每10秒钟更新一行的丢失时间和状态列.状态和丢失时间(以及主索引)都有索引.

我注意到大型数据库(即其他表有很多条目,而不是表W)在一段时间内,查询变得越来越慢,越来越慢.运行48小时后,我通过在PqAdminIII的查询窗口中运行它来计时,它需要17分钟才能执行!

我在另一个显示相同问题的表上有类似的查询:

UPDATE H SET release='1' 
WHERE a NOT IN (SELECT id from A WHERE state!='done') AND release!='1';
Run Code Online (Sandbox Code Playgroud)

H没有任何索引,但我尝试在H(发布)上放置和删除索引而不改变行为.在数据库已经运行48小时并且表H有大约100k行之后,此查询需要27分钟.Postgres服务器在查询期间将有一个完全挂钩的线程(100%CPU利用率),因此它看起来不像是对网络,磁盘等的任何争用.

因此,从广义上看,我看到的行为是我的数据库按预期运行大约5分钟,然后逐渐停止所有内容,因为基本的维护相关UPDATE命令开始运行的时间越来越长.到第二天,花一个小时做一个简单的维护周期(一些更新),一开始就运行~100ms.我似乎很清楚,性能下降与数据库中的信息量是超线性的 - 可能是N ^ 2或其他一些.

Autovacuum正在使用默认值.我仔细阅读了手册,并没有看到任何跳出来的东西.

我在这里挠头.我没有看到任何在9.0.1和9.0.2发行说明中看起来相关的错误修复.谁能帮我理解发生了什么?谢谢,M

-xxxx-

好的,我可能在这里遇到两个问题.

第一次更新似乎现在运行得很快.不确定发生了什么,所以我将继续假设我需要更频繁地运行VACUUM/ANALYZE或某种组合 - 比如每分钟左右.我真的很想知道为什么autovacuum不会这样做.

第二次更新继续缓慢运行.查询计划表明索引没有得到有效使用,并且发生了80k*30k的交叉,这可能是我似乎正在观察的超线性运行时的原因.(大家都同意这个计划的解释吗?)

我可以将UPDATE转换为SELECT:

SELECT * from H
where a not in (SELECT id from A where state='done') AND release!='1';
Run Code Online (Sandbox Code Playgroud)

具有类似的运行时间(27分钟).

如果我不相信postgres优化器并执行此操作:

WITH r as (select id from A where state='done')
SELECT a from H 
JOIN …
Run Code Online (Sandbox Code Playgroud)

sql postgresql vacuum sql-update

5
推荐指数
1
解决办法
683
查看次数

Postgres:一张多列的表还是几张少列的表?

我的问题与 Postgres 的工作原理有关:

我有一张桌子:


CREATE TABLE A (
   id SERIAL,  
   name VARCHAR(32),
   type VARCHAR(32) NOT NULL, 
   priority SMALLINT NOT NULL,
   x SMALLINT NOT NULL,
   y SMALLINT NOT NULL,
   start timestamp with time zone,
   end timestamp with time zone,
   state Astate NOT NULL,
   other_table_id1 bigint REFERENCES W,
   other_table_id2 bigint NOT NULL REFERENCES S,
   PRIMARY KEY(id)
); 
Run Code Online (Sandbox Code Playgroud)

在 other_table_id1、state 和 other_table_id2 上附加索引。

该表非常大,并且在列上看到了很多更新:other_table_id1、state。开始和结束列的一些更新,但其余的都是不可变的。(Astate 是列状态的枚举类型。)

我想知道将两个最常更新的列拆分到一个单独的表中是否有意义。我希望获得的是性能,因为当我只是查找该信息时,或者减少更新的权重,因为(也许?)读取和写入较短的行成本较低。但是,当(偶尔)需要一次性获得特定项目的所有数据时,我需要将其与连接成本进行权衡。

有一次,我的印象是每一列都是单独存储的。但是后来,当我在某处读到减少表格一侧列的宽度确实会对使用另一列查找数据时的性能产生积极影响时,我修改了我的想法(因为该行存储在一起,因此总行长度将更短)。所以我现在的印象是一行的所有数据都物理存储在磁盘上;所以提议的表格拆分听起来会很有帮助。当我当前写入 4 个字节来更新状态时,我是否相信我正在重写实际上从未改变的 64 个字节的文本(名称、类型)?

我对表“规范化”不是很熟悉,也不熟悉 Postgres 的内部结构,所以我正在寻找建议和 esp 最佳实践来估计权衡,而不必先做工作,然后确定这项工作是否值得. 这种变化需要相当多的努力来重写已经高度优化的查询,所以我宁愿深入了解我可以期待什么结果。谢谢,M。

sql postgresql database-design data-modeling

5
推荐指数
1
解决办法
4084
查看次数