繁体   English   中英

ON DELETE CACADE非常慢

[英]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可能会更好。 它们整体较小,速度更快。 如果确实需要实施最大值,则始终可以添加检查约束。

  • 我也将使用text代替varchar(n)

  • 并对进行重新排序 (在表创建时)。 根据经验,应将固定长度的NOT NULL列放在第一位。 timestampinteger放在首位,将numerictext放在最后。 这里更多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM