临时表膨胀pg_attribute

问题描述 投票:3回答:2

我正在使用COPY从CSV中将大批量数据插入我们的数据库。插件看起来像这样:

-- This tmp table will contain all the items that we want to try to insert
CREATE TEMP TABLE tmp_items
(
    field1 INTEGER NULL,
    field2 INTEGER NULL,
    ...
) ON COMMIT DROP;

COPY tmp_items(
    field1,
    field2,
    ...
) FROM 'path\to\data.csv' WITH (FORMAT csv);

-- Start inserting some items
WITH newitems AS (
    INSERT INTO items (field1, field2)
    SELECT tmpi.field1, tmpi,field2
    FROM tmp_items tmpi
    WHERE some condition

    -- Return the new id and other fields to the next step
    RETURNING id AS newid, field1 AS field1
)
-- Insert the result into another temp table
INSERT INTO tmp_newitems SELECT * FROM newitems;

-- Use tmp_newitems to update other tables
etc....

何时将使用tmp_items中的数据在多个表中执行多次插入。我们在插入之前检查重复项并以几种方式操作数据,因此不会按原样使用或插入tmp_items中的所有内容。我们通过CTE和更多临时表的组合来实现这一点。

这非常有效,并且足以满足我们的需求。我们做了很多这些,我们遇到的问题是pg_attribute变得非常臃肿非常快,autovacuum似乎无法跟上(并消耗大量的CPU)。

我的问题是:

  1. 是否可以在不使用临时表的情况下执行此类插入?
  2. 如果没有,我们是否应该让qazxsw poi的autovacuum更具侵略性?不会占用那么多CPU吗?
postgresql postgresql-9.6
2个回答
3
投票

最好的解决方案是在会话开始时创建临时表

pg_attribute

然后临时表将在会话期间保留,但在每次提交时都会清空。

这将大大减少CREATE TEMPORARY TABLE ... ( ... ) ON COMMIT DELETE ROWS; 的膨胀,并且腹胀不应该成为一个问题。

你也可以加入黑暗的一面(警告,这是不受支持的):

  • 启动PostgreSQL pg_attribute 这样您就可以修改系统目录。
  • 以超级用户身份连接并运行 pg_ctl start -o -O

现在autovacuum将在UPDATE pg_catalog.pg_class SET reloptions = ARRAY['autovacuum_vacuum_cost_delay=0'] WHERE oid = 'pg_catalog.pg_attribute'::regclass; 上更积极地运行,这可能会解决你的问题。

请注意,重大升级后设置将会消失。


2
投票

我知道这是一个老问题,但有些人可能会在将来找到我的帮助。

因此,我们对具有> 500 rps的临时表和通过nodejs的async i \ o非常沉重,因此经历了非常沉重的pg_attribute膨胀。你剩下的只是一个非常激进的吸尘器,它会停止性能。这里给出的所有答案都没有解决这个问题,因为丢弃和重新创建临时表会大量占用pg_attribute,因此一个阳光明媚的早晨你会发现数据库性能已经死亡,pg_attribute 200+ gb而你的数据库就像10gb一样。

所以这个解决方案很优雅

pg_attribute

所以你继续玩临时表,保存你的pg_attribute,没有黑暗的重型吸尘,并获得所需的性能。

别忘了

create temp table if not exists my_temp_table (description) on commit delete rows;

干杯:)

© www.soinside.com 2019 - 2024. All rights reserved.