c# - PostgreSQL:在有外键的多表中插入大量

标签 c# postgresql foreign-keys npgsql

因此,我正在从事一个项目,该项目涉及在一天内将大量数据插入到三个主表中。这三个表都相互链接。

表格如下:

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$$; 命令。我可以声明临时整数值并捕获我插入的 eventssubevents 的 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/

相关文章:

使用继承和外键时,Django syncdb 冲突related_name

c# - 访问网络路径并将文件复制到系统= c#

postgresql - 单个事务中的多个 SELECT FOR UPDATES 是否会导致竞争条件 (Postgres)?

c# - 如何在 C# 中的 azure 认知搜索结果中返回 search.score

PostgreSQL - 获取指定角色对每个对象类型的有效权限

django - 每天在特定时间清除表中的数据

php - Firebird 上的外键问题

mysql - 主键列不允许空值

c# - 可折叠的主细节 GridView 结构

c# - Xamarin.Android -> WebView -> 未打开上传或拍摄图像选项