在我的职业生涯中,我遇到过很多这样的例子:必须将扁平的、非规范化的数据插入到规范化的结构中。
为了实现这一点,我经常使用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;
但是,从性能的Angular 来看,必须返回并重新扫描原始数据表似乎很遗憾。i、 e.一次插入 foo
然后再次插入 bar
.
我很想知道这是否是一个最佳的方法,或者,如果不是,可以做些什么来改善它。
2条答案
按热度按时间g2ieeal71#
是的,但是想想看,如果你有足够的内存来保存json,那么你就有足够的内存来保存这个表。因此,两次传递数据可能会更快。磁盘1次,内存1次。正因为这个原因,dbms倾向于在内存中保留最常使用的数据。免责声明:我的主要经验是与甲骨文,所以我可能会投影到postgres在这里,但我认为它做这个缓冲。
sg3maiej2#
我已经玩了一段时间了,我想把这个作为一个可能的建议。如果使用cte将数据放入json结构(手工生成pks),然后从中插入每个表,会怎么样?
这样地:
它只需扫描原始数据一次。我还没有完全考虑到cte、json等的性能问题。我很感激对这种方法的任何批评,我仍然会坚持一个更好(或不那么奇怪)的答案。