我的询问
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)。
我无法将时间缩短到合理的长度:
此外,在删除之前执行真空分析,并且不应有任何锁定(仅数据库中的活动查询)。
我还没有尝试复制到临时表并截断 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)"
我在 Postgres 16 上遇到了同样的问题(通过主键删除,所以不是顺序搜索问题),需要使用
manual VACUUM
而不是依赖 auto_vacuum
来修复它:
VACUUM (PARALLEL 3) my_tables
VACUUM ANALYZE
我通过 cron 运行它
我的完整 HTTP 请求的持续时间现在为 300 毫秒,而不是之前的 2.5 秒
我应该调查为什么
auto_vacuum
不能通过 istelf 完成这项工作,但有一个命令来手动触发它总是好的。
希望这能有所帮助