因此,我正在从事一个项目,该项目涉及在一天内将大量数据插入到三个主表中。这三个表都相互链接。
表格如下:
event
user_id
event_time
event_id (PRIMARY) (Serial Int)
subevent
subevent_type
subevent_value
subevent_id (PRIMARY) (Serial Int)
event_relationship
event_id (1)
subevent_id (MANY)
事件
随时可能发生,当它们发生时,我需要记录子事件
的详细信息并将它们插入数据库。一个 event
中可以有 5 到 500 个 subevents
。我在 subevents
中有一个关系表而不仅仅是外键列的原因是因为还有其他进程将值添加到 subevents
而没有父级 事件
。可能会令人困惑。
到一天结束时,我可能已经插入了多达 1000 万个子事件
和 250,000 个事件
。所以速度对我来说是最重要的事情之一。我发现将它们全部插入在一起的最佳方法之一是使用 DO $$ DECLARE ... END$$;
命令。我可以声明临时整数值并捕获我插入的 events
和 subevents
的 ID,然后将它们一起插入到 event_relationship
表中。
这是我当前正在运行的代码,它作为 PL/pgSql 执行
DO $$ DECLARE _new_event_id INTEGER; _new_subevent_id INTEGER;
BEGIN
INSERT INTO event (user_id, event_time) VALUES (@user_id, @event_time)
RETURNING event_id INTO _new_event_id;
INSERT INTO subevent (subevent_type, subevent_value)
VALUES (@subevent_type, @subevent_value)
RETURNING subevent_id INTO _new_subevent_id;
INSERT INTO event_relationship VALUES (_new_event_id, _new_subevent_id);
END$$;
(第一次插入只有一次,对于每个子事件重复最后两次插入。我使用 C# 和 NpgSql 执行命令,并且可以在进程运行时动态构建命令。)
但是,在一天的过程中,这陷入了困境,我的数据开始备份到我无法足够快地全部插入的地步。我只是想知道我是否在这里采用了错误的方法,或者是否有另一种方法可以更快地完成我已经在做的事情。
最佳答案
你可以有一个外键关系并在引用表中插入null
:
create table t (i int primary key);
create table t2 (i int references t (i));
insert into t2 (i) values (null);
INSERT 0 1
insert into t2 (i) values (1);
ERROR: insert or update on table "t2" violates foreign key constraint "t2_i_fkey"
DETAIL: Key (i)=(1) is not present in table "t".
或者在引用表中有一个特殊值,如零或 -1 以用于“孤儿”子事件。
为了减轻负载,您可以在单个命令中插入子事件:
insert into subevent (subevent_type, subevent_value) values
(@subevent1_type, @subevent1_value),
(@subevent2_type, @subevent2_value);
关于c# - PostgreSQL:在有外键的多表中插入大量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18260082/