我有一个与 ON DELETE CASCADE 性能相关的问题。我试图理解为什么需要这么长时间。出于本主题的目的,我将真实案例简化为如下所示的模式:
CREATE TABLE IF NOT EXISTS public.items
(
id uuid NOT NULL,
name text COLLATE pg_catalog."default",
CONSTRAINT items_pk PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS public.links
(
parent uuid,
child uuid,
CONSTRAINT links_parent_fk FOREIGN KEY (parent)
REFERENCES public.items (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE,
CONSTRAINT links_child_fk FOREIGN KEY (child)
REFERENCES public.items (id) MATCH SIMPLE
ON UPDATE CASCADE
ON DELETE CASCADE
);
CREATE INDEX IF NOT EXISTS parent_idx
ON public.links USING btree
(parent ASC NULLS LAST);
CREATE INDEX IF NOT EXISTS child_idx
ON public.links USING btree
(child ASC NULLS LAST);
CREATE EXTENSION "uuid-ossp";
并且可以通过以下方式生成数据:
INSERT INTO public.items
SELECT uuid_generate_v4 (), 'item_' || i
FROM generate_series(1, 134001) AS i;
INSERT INTO links
SELECT (SELECT id FROM public.items WHERE name='item_1'), id FROM public.items;
简而言之,数据库包含两个表。表
items
包含项目列表(标识符和名称列)和表links
定义项目(父<->子)之间的关系。在呈现的情况下,所有项目(子项)都属于名为“item_1”(父项)的项目。
我调用查询以删除分配给父母的所有孩子:
BEGIN;
EXPLAIN ANALYZE DELETE FROM public.items where id in (SELECT child FROM public.links WHERE parent = (SELECT id FROM public.items WHERE name='item_1'));
ROLLBACK;
从执行计划中我们可以读到:
“约束 links_parent_fk 的触发器:time=10451.471 calls=134001”
“约束 links_child_fk 的触发器:time=2962.035 calls=134001”
问题是为什么trigger for constraint
links_parent_fk
会消耗很多时间?
我尝试在
links
表中的列之间交换数据。之后,links_child_fk
的触发消耗了 ~10 秒,而 links_parent_fk
的触发消耗了 ~3 秒。我很好奇为什么执行这个删除级联之间会有这样的差异?
PostgreSQL 版本:12.4 和 13.9.
PostgreSQL 在 Linux 上肯定比在 Windows 上运行得更快(而且我 作为编写它的 windows 端口的人之一说这个..)它是 专为 Unix 风格的架构设计,并实现了相同的 Windows 上的体系结构,这意味着它可以做很多事情 Windows 的设计并不是为了做好。它工作正常,但它没有 表现也一样。
马格努斯·哈甘德
我在 Azure 上使用 Postgres 时亲眼目睹了这一点,当时它是 windows postgres。我认为由于性能问题,他们已经/正在转向 Linux postgres。
因此,我认为在性能很重要的情况下,在 windows 上测试 Postgres 性能并在 windows 上运行 Postgres 没有意义,最好使用不同的操作系统或不同的 RDBMS。