Postgres删除超级慢,如何改进?

问题描述 投票:0回答:1

我的询问

delete from test.t1 where t2_id = 1;

我的主表是t1(包含大约1M行,需要删除大约100k行)

CREATE TABLE test.t1
(
  id bigserial NOT NULL,
  t2_id bigint,
  ... other fields
  CONSTRAINT pk_t1 PRIMARY KEY (id),
  CONSTRAINT fk_t1_t2 FOREIGN KEY (t2_id)
      REFERENCES test.t2 (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

我在 t2_id 上有索引,在纯字符串字段上有 3 个其他索引。

CREATE INDEX t1_t2_idx ON test.t1 USING btree (t2_id);

有多个(大约 50 个)表引用 test.t1。我在 t1_id 上为引用它的每个表都有一个索引。

CREATE TABLE test.t7
(
  id bigserial NOT NULL,
  t1_id bigint,
  ... other fields
  CONSTRAINT pk_objekt PRIMARY KEY (id),
  CONSTRAINT fk_t7_t1 FOREIGN KEY (t1_id)
      REFERENCES test.t1 (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)

CREATE INDEX t7_t1_idx ON test.t7 USING btree (t1_id);
//No other indexes here

t7 的内容在 t1 之前被删除,与从 t1 中删除相比,速度非常快。要删除的行的比率相同 (~10%),但总行数要少得多(大约 100K)。

我无法将时间缩短到合理的长度:

  • 我尝试删除所有索引(24小时后取消)
  • 仅保留 t1_t2_idx 和 t7_t1_idx ... t50_t1_idx 索引(24 小时后取消)
  • 保留所有索引(24小时后取消)

此外,在删除之前执行真空分析,并且不应有任何锁定(仅数据库中的活动查询)。

我还没有尝试复制到临时表并截断 t1,但这似乎不合理,因为 t1 可以增长到 10M 行,其中 1M 需要在某个时候删除。

有什么想法可以改善去除效果吗?

编辑

非常确定没有锁,因为 pg_stat_activity 仅显示 2 个活动查询(删除和 pg_stat_activity)

"Delete on test.t1 (cost=0.43..6713.66 rows=107552 width=6)"
"  ->  Index Scan using t1_t2_idx on test.t1 (cost=0.43..6713.66 rows=107552 width=6)"
"        Output: ctid"
"        Index Cond: (t1.t1_id = 1)"
postgresql
1个回答
0
投票

我在 Postgres 16 上遇到了同样的问题(通过主键删除,所以不是顺序搜索问题),需要使用

manual VACUUM
而不是依赖
auto_vacuum
来修复它:

VACUUM (PARALLEL 3) my_tables
VACUUM ANALYZE

我通过 cron 运行它

我的完整 HTTP 请求的持续时间现在为 300 毫秒,而不是之前的 2.5 秒

我应该调查为什么

auto_vacuum
不能通过 istelf 完成这项工作,但有一个命令来手动触发它总是好的。

希望这能有所帮助

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