[英]ON DELETE CACADE is very slow
我正在使用Postgres 8.4。 我的系统配置是window 7 32 bit 4 gb ram和2.5ghz。
我在Postgres中有一个数据库,其中有10个表t1, t2, t3, t4, t5.....t10
。
t1
有一个主键和一个序列ID,它是对所有其他表的外键引用。
数据插入到数据库中(即所有表中),除了t1
之外,其他所有表都有近50,000行数据,而t1
有一个1行,其主键从所有其他表中引用。 然后,我在t1中插入第二行数据,并在其他表中再次插入50,000行,并添加此新引用。
问题是当我想删除其他表中存在的所有数据条目时:
delete from t1 where column1='1'
该查询将花费近10分钟的时间来执行。
我也创建了索引并尝试过,但是性能根本没有提高。 该怎么办?
我在下面提到了一个示例架构
CREATE TABLE t1
(
c1 numeric(9,0) NOT NULL,
c2 character varying(256) NOT NULL,
c3ver numeric(4,0) NOT NULL,
dmlastupdatedate timestamp with time zone NOT NULL,
CONSTRAINT t1_pkey PRIMARY KEY (c1),
CONSTRAINT t1_c1_c2_key UNIQUE (c2)
);
CREATE TABLE t2
(
c1 character varying(100),
c2 character varying(100),
c3 numeric(9,0) NOT NULL,
c4 numeric(9,0) NOT NULL,
tver numeric(4,0) NOT NULL,
dmlastupdatedate timestamp with time zone NOT NULL,
CONSTRAINT t2_pkey PRIMARY KEY (c3),
CONSTRAINT t2_fk FOREIGN KEY (c4)
REFERENCES t1 (c1) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE,
CONSTRAINT t2_c3_c4_key UNIQUE (c3, c4)
);
CREATE INDEX t2_index ON t2 USING btree (c4);
让我知道架构是否有问题。
对于更大的表和超过两个或三个值,您需要在引用列( t1.c1
)和引用列( t2.c4
,...)上建立索引。
但是,如果您的描述准确无误,则不会导致您的方案出现性能问题。 由于在t1
只有2个不同的值,因此索引没有用。 顺序扫描将更快。
无论如何,我重新制定了您在Postgres 9.1.9中描述的内容
CREATE TABLE t1
( c1 numeric(9,0) PRIMARY KEY,
c2 character varying(256) NOT NULL,
c3ver numeric(4,0) NOT NULL,
dmlastupdatedate timestamptz NOT NULL,
CONSTRAINT t1_uni_key UNIQUE (c2)
);
CREATE temp TABLE t2
( c1 character varying(100),
c2 character varying(100),
c3 numeric(9,0) PRIMARY KEY,
c4 numeric(9,0) NOT NULL,
tver numeric(4,0) NOT NULL,
dmlastupdatedate timestamptz NOT NULL,
CONSTRAINT t2_uni_key UNIQUE (c3, c4),
CONSTRAINT t2_c4_fk FOREIGN KEY (c4)
REFERENCES t1(c1) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
);
INSERT INTO t1 VALUES
(1,'OZGPIGp7tgp97tßp97tß97tgP?)/GP)7gf', 234, now())
,(2,'agdsOZGPIGp7tgp97tßp97tß97tgP?)/GP)7gf', 4564, now());
INSERT INTO t2
SELECT'shOahaZGPIGp7tgp97tßp97tß97tgP?)/GP)7gf'
,'shOahaZGPIGp7tgp97tßp97tß97tgP?)/GP)7gf'
, g, 2, 456, now()
from generate_series (1,50000) g
INSERT INTO t2
SELECT'shOahaZGPIGp7tgp97tßp97tß97tgP?)/GP)7gf'
,'shOahaZGPIGp7tgp97tßp97tß97tgP?)/GP)7gf'
, g, 2, 789, now()
from generate_series (50001, 100000) g
ANALYZE t1;
ANALYZE t2;
EXPLAIN ANALYZE DELETE FROM t1 WHERE c1 = 1;
总运行时间:53.745毫秒
DELETE FROM t1 WHERE c1 = 1;
58毫秒的执行时间。
因此,您的架构布局从根本上没有错 。
次要增强功能:
您有几个定义为numeric(9,0)
或numeric(4,0)
。 除非您有充分的理由这样做,否则仅使用integer
可能会更好。 它们整体较小,速度更快。 如果确实需要实施最大值,则始终可以添加检查约束。
并对列进行重新排序 (在表创建时)。 根据经验,应将固定长度的NOT NULL列放在第一位。 将timestamp
和integer
放在首位,将numeric
或text
放在最后。 这里更多。 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.