sql性能:将一个表插入到两个表中

huwehgph  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(335)

在我的职业生涯中,我遇到过很多这样的例子:必须将扁平的、非规范化的数据插入到规范化的结构中。
为了实现这一点,我经常使用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 .
我很想知道这是否是一个最佳的方法,或者,如果不是,可以做些什么来改善它。

g2ieeal7

g2ieeal71#

是的,但是想想看,如果你有足够的内存来保存json,那么你就有足够的内存来保存这个表。因此,两次传递数据可能会更快。磁盘1次,内存1次。正因为这个原因,dbms倾向于在内存中保留最常使用的数据。免责声明:我的主要经验是与甲骨文,所以我可能会投影到postgres在这里,但我认为它做这个缓冲。

sg3maiej

sg3maiej2#

我已经玩了一段时间了,我想把这个作为一个可能的建议。如果使用cte将数据放入json结构(手工生成pks),然后从中插入每个表,会怎么样?
这样地:

WITH raw_as_json AS (
    SELECT
        jsonb_build_object(
            'id', NEXTVAL('foo_seq'),
            'value', foo,
            'bars', json_build_array(bar_1, bar_2)
        ) AS foobar
    FROM raw_data
), foos AS (
    INSERT INTO foo (id, value)
    SELECT
        (foobar -> 'id')::int,
        foobar -> 'value'
    FROM raw_as_json
)
INSERT INTO bar (id, foo_id, value)
SELECT
    NEXTVAL('bar_seq'),
    (foobar -> 'id')::int,
    jsonb_array_elements_text(foobar -> 'bars')
FROM raw_as_json;

它只需扫描原始数据一次。我还没有完全考虑到cte、json等的性能问题。我很感激对这种方法的任何批评,我仍然会坚持一个更好(或不那么奇怪)的答案。

相关问题