【发布时间】:2020-06-24 11:14:53
【问题描述】:
在我的职业生涯中,我遇到过许多必须将平面、非规范化数据插入规范化结构的实例。
为此,我经常使用 CTE 插件。例如
CREATE TABLE raw_data (
foo varchar,
bar_1 varchar,
bar_2 varchar
);
INSERT INTO raw_data VALUES ('A', 'A1', 'A2');
INSERT INTO raw_data VALUES ('B', 'B1', 'B2');
CREATE TABLE foo (
id int PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
value varchar NOT NULL
);
CREATE TABLE bar (
id int PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
value varchar NOT NULL,
foo_id int NOT NULL,
CONSTRAINT fk_bar_foo FOREIGN KEY (foo_id) REFERENCES foo(id)
);
WITH new_foos AS (
INSERT INTO foo (value)
SELECT foo FROM raw_data
RETURNING *
)
INSERT INTO bar (foo_id, value)
SELECT
f.id,
unnest(ARRAY[r.bar_1, r.bar_2])
FROM new_foos f
JOIN raw_data r
ON r.foo = f.value;
它工作正常,但是从性能的角度来看,不得不返回并重新扫描原始数据表似乎很可惜。 IE。一次插入foo,然后再次插入bar。
我很想知道这是否是一种最佳方法,或者如果不是,可以做些什么来改进它。
【问题讨论】:
-
我认为没有办法绕过
join——也就是说,您不能返回表中没有的值。如果您在raw_data(foo)上有索引,那么性能应该不错。 -
我想这取决于你对好的定义,有时像这样的 raw_data 导入会变得非常大。我内心有一个小声音说:“除非你真的必须这样做,否则不要多次访问你的大桌子”。您可能是对的,但我从未停止对 SQL 社区提出的一些解决方案感到惊讶,所以我只是想把这个扔出去!
标签: sql postgresql performance