Postgres中的大插入后慢查询

xpa*_*pad 3 sql postgresql batch-processing postgresql-9.2 postgresql-performance

我们在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);
Run Code Online (Sandbox Code Playgroud)

作为批处理作业的一部分,我们首先使用新的BULK_ID向表中添加许多行.所有新记录都有CHUNK_ID = NULL,STATE ='PENDING'.插入物在500K和1.5M行之间.发生这种情况时,表的大小超过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)
Run Code Online (Sandbox Code Playgroud)

每次块迭代增加$ 1,$ 2$ 3总是相同(刚刚插入BULK_ID),$ 4通常在2,000到10,000之间.

问题是前几个块需要很长时间才能更新.例如,对于2000的限制,大多数更新发生在1秒以内,而前几个更新需要2分钟.

我们试图了解为什么会发生这种情况以及如何解决这个问题.阅读文档后:

为确保数据页的一致性,每个检查点之后对数据页的第一次修改会导致记录整个页面内容.

我们认为这与检查站和WAL有关,但我们无法确定它.

有什么建议?

Erw*_*ter 5

ANALYZE

自动清理后台程序也运行ANALYZE自动,但它需要一些时间来踢.如果你运行UPDATE后,一个巨大的立即INSERT,确保运行ANALYZE 之间的更新统计,或查询规划可能会做出错误的选择.

FROM 条款而不是 IN

IN众所周知,大型子查询很慢.这可能会更好:

UPDATE base_bulk_wi wi
SET   wi.state = 'PROCESSING'
    , wi.chunk_id = $1 
FROM (
    SELECT user_id, bulk_id 
    FROM   base_bulk_wi
    WHERE  bulk_id = $3 
    AND    chunk_id IS NULL
    AND    state = 'PENDING'
    LIMIT  $4
    FOR    UPDATE
    ) x 
WHERE wi.bulk_id = x.bulk_id
AND   wi.user_id = x.user_id;
Run Code Online (Sandbox Code Playgroud)

索引

像这样的部分索引应该是您的最佳选择:

CREATE INDEX base_bulk_wi_partial_idx01 ON bulk_wi(chunk_id)
WHERE state = 'PENDING' AND chunk_id IS NULL;
Run Code Online (Sandbox Code Playgroud)

为获得最佳性能,请您的后面创建此索引INSERT.如果它已经存在,则可能有助于之前删除并重新创建.

有人可能认为在Postgres 9.2中包含bulk_id这个索引以允许仅索引扫描是个好主意.但是既然你已经FOR UPDATE在子查询中,那么无论如何这都不是一个选择.

它会有所帮助,如果user_id是一个integer而不是varchar.(用户表的外键.)除了更快的处理和更小的表,两个整数完全适合最小尺寸索引.你的主键会受益很多.