临时表膨胀 pg_attribute
Temporary tables bloating pg_attribute
我正在使用 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).
我的问题是:
- 是否可以在不使用临时表的情况下执行这种插入?
- 如果不是,我们是否应该让
pg_attribute
的 autovacuum 更激进?这不会占用更多或更多 CPU 吗?
最好的解决方案是在会话开始时创建临时表
CREATE TEMPORARY TABLE ... (
...
) ON COMMIT DELETE ROWS;
然后临时表将在会话期间保留,但在每次提交时清空。
这将显着减少 pg_attribute
的肿胀,腹胀不再是问题。
你也可以加入黑暗面(警告,这是不受支持的):
使用
启动 PostgreSQL
pg_ctl start -o -O
以便您可以修改系统目录。
以超级用户身份连接并 运行
UPDATE pg_catalog.pg_class
SET reloptions = ARRAY['autovacuum_vacuum_cost_delay=0']
WHERE oid = 'pg_catalog.pg_attribute'::regclass;
现在 autovacuum 将 运行 在 pg_attribute
上更加积极,这可能会解决您的问题。
请注意,重大升级后设置将消失。
我知道这是一个老问题,但以后有人可能会发现我的帮助在这里很有用。
因此,我们对具有 >500 rps 的临时 tables 和通过 nodejs 的异步 i\o 非常重视,因此经历了非常严重的 pg_attribute 膨胀。剩下的就是非常激进的吸尘,这会停止性能。
此处给出的所有答案都不能解决这个问题,因为删除和重新创建临时 table 会使 pg_attribute 严重膨胀,因此在一个阳光明媚的早晨你会发现数据库性能下降,并且 pg_attribute 200+ gb 而你的数据库就像 10gb.
所以这个解决方案很优雅
create temp table if not exists my_temp_table (description) on commit delete rows;
所以你继续使用温度 tables,保存你的 pg_attribute,没有暗面大量吸尘并获得所需的性能。
别忘了
vacuum full pg_depend;
vacuum full pg_attribute;
干杯:)
我正在使用 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).
我的问题是:
- 是否可以在不使用临时表的情况下执行这种插入?
- 如果不是,我们是否应该让
pg_attribute
的 autovacuum 更激进?这不会占用更多或更多 CPU 吗?
最好的解决方案是在会话开始时创建临时表
CREATE TEMPORARY TABLE ... (
...
) ON COMMIT DELETE ROWS;
然后临时表将在会话期间保留,但在每次提交时清空。
这将显着减少 pg_attribute
的肿胀,腹胀不再是问题。
你也可以加入黑暗面(警告,这是不受支持的):
使用
启动 PostgreSQLpg_ctl start -o -O
以便您可以修改系统目录。
以超级用户身份连接并 运行
UPDATE pg_catalog.pg_class SET reloptions = ARRAY['autovacuum_vacuum_cost_delay=0'] WHERE oid = 'pg_catalog.pg_attribute'::regclass;
现在 autovacuum 将 运行 在 pg_attribute
上更加积极,这可能会解决您的问题。
请注意,重大升级后设置将消失。
我知道这是一个老问题,但以后有人可能会发现我的帮助在这里很有用。
因此,我们对具有 >500 rps 的临时 tables 和通过 nodejs 的异步 i\o 非常重视,因此经历了非常严重的 pg_attribute 膨胀。剩下的就是非常激进的吸尘,这会停止性能。 此处给出的所有答案都不能解决这个问题,因为删除和重新创建临时 table 会使 pg_attribute 严重膨胀,因此在一个阳光明媚的早晨你会发现数据库性能下降,并且 pg_attribute 200+ gb 而你的数据库就像 10gb.
所以这个解决方案很优雅
create temp table if not exists my_temp_table (description) on commit delete rows;
所以你继续使用温度 tables,保存你的 pg_attribute,没有暗面大量吸尘并获得所需的性能。
别忘了
vacuum full pg_depend;
vacuum full pg_attribute;
干杯:)