想象一下关于猫主人的下表。
drop table if exists owners cascade;
create table owners(
id bigint primary key generated always as identity ,
name text not null
)
;
insert into owners(name)
select random()::text from generate_series(1,20000);
--insert 200,000 owners records
当我删除一些所有者记录时,它非常快:
delete from owners
where id %10 = 0;
20000 行在 85 毫秒内受影响
现在我添加一个名为“cats”的表,它指的是所有者:
drop table if exists cats;
create table cats(
id serial primary key ,
name varchar(20000) not null,
owner_id int not null references owners(id)
);
--insert 1bn cats records
insert into cats(name, owner_id)
select
random()::text,
owners.id
from generate_series(1,10), owners;
让我们删除一些所有者,但首先我们必须删除这些所有者“拥有”的猫:
--delete the records in cats so we don't get a foreign key constraint violation
delete from cats
where owner_id %10 = 1;
---now we do the same delete on owners as we did before
delete from owners
where id %10 = 1;
2000 行在 25 秒 828 毫秒内受影响
为什么第二次删除所有者的速度比我们没有 cat 表时慢约 5000 倍?
cats
这是在删除期间检查所有者是否仍然被表引用。检查实质上是select * from cats where owner_id = ?
对您删除的每个所有者使用 a 来完成的。您可以通过在外键列上创建索引来加快检查速度: