我们在 RedHat 中使用 Postgres 9.2。我们有一个类似于以下的表:
CREATE TABLE BULK_WI (
BULK_ID INTEGER NOT NULL,
USER_ID VARCHAR(20) NOT NULL,
CHUNK_ID INTEGER,
STATE VARCHAR(16),
CONSTRAINT BASE_BULK_WI_PK PRIMARY KEY(BULK_ID,USER_ID)
);
CREATE INDEX BASE_BULK_WI_IDX01 ON BULK_WI(STATE, CHUNK_ID);
作为批处理作业的一部分,我们首先使用新的 BULK_ID 向表中添加一些行。所有新记录的 CHUNK_ID = NULL,STATE = 'PENDING'。插入在 500K 到 150 万行之间。发生这种情况时表的大小超过 15M 记录。
插入后,我们开始分块处理表。为此,我们首先为下一个块选择一些项目,然后处理它们。通过以下查询选择项目:
UPDATE BASE_BULK_WI wi SET wi.STATE = 'PROCESSING', wi.CHUNK_ID = $1
WHERE wi.STATE='PENDING' AND wi.BULK_ID = $2
AND wi.USER_ID IN
(SELECT USER_ID FROM BASE_BULK_WI WHERE BULK_ID = $3
AND CHUNK_ID IS NULL AND STATE='PENDING' LIMIT $4 FOR UPDATE)
$1每次块迭代都会增加,$2和$3始终相同(刚刚插入的 BULK_ID),$4通常在 2,000 到 10,000 之间。
问题是前几个块需要很长时间才能更新。例如,对于 2000 的限制,大多数更新发生在 1 秒内,而前几个更新需要 2 分钟以上。
我们正试图了解为什么会发生这种情况以及如何解决它。阅读文档后:
为了确保数据页的一致性,在每个检查点之后对数据页的第一次修改会导致记录整个页面内容。
我们认为它与检查站和 WAL 有关,但我们无法确定它。
有什么建议么?