我有一个应用程序,需要将用户指定的CSV文件中的数据加载到PostgreSQL数据库表中。
CSV文件的结构很简单:
name,email
John Doe,john@example.com
...
在数据库中,我有三个表:
---------------
-- CAMPAIGNS --
---------------
CREATE TABLE "campaigns" (
"id" serial PRIMARY KEY,
"name" citext UNIQUE CHECK ("name" ~ '^[-a-z0-9_]+$'),
"title" text
);
----------------
-- RECIPIENTS --
----------------
CREATE TABLE "recipients" (
"id" serial PRIMARY KEY,
"email" citext UNIQUE CHECK (length("email") <= 254),
"name" text
);
-----------------
-- SUBMISSIONS --
-----------------
CREATE TYPE "enum_submissions_status" AS ENUM (
'WAITING',
'SENT',
'FAILED'
);
CREATE TABLE "submissions" (
"id" serial PRIMARY KEY,
"campaignId" integer REFERENCES "campaigns" ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
"recipientId" integer REFERENCES "recipients" ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,
"status" "enum_submissions_status" DEFAULT 'WAITING',
"sentAt" timestamp with time zone
);
CREATE UNIQUE INDEX "submissions_unique" ON "submissions" ("campaignId", "recipientId");
CREATE INDEX "submissions_recipient_id_index" ON "submissions" ("recipientId");
我想读取指定CSV文件中的所有行,并确保recipients
和submissions
表中存在相应记录。
在这些表中加载数据的性能最有效的方法是什么?
这主要是一个概念性问题,我不是要求具体实施。
首先,我天真地尝试逐行阅读和解析CSV文件,并为每封电子邮件发出SELECT/INSERT
次查询。显然,这是一个非常缓慢的解决方案,允许我每分钟加载~4k记录,但代码非常简单明了。
现在,我逐行读取CSV文件,但将所有电子邮件聚合成一批1000个元素。所有SELECT/INSERT
个查询都是使用SELECT id, email WHERE email IN ('...', '...', '...', ...)
构造批量生成的。这种方法提高了性能,现在我的性能达到每分钟约25k。但是,这种方法要求使用相当复杂的多步骤代码。
有没有更好的方法来解决这个问题并获得更好的性能?
这里的关键问题是我需要先将数据插入recipients
表,然后我需要使用生成的id
在submissions
表中创建相应的记录。
另外,我需要确保插入的电子邮件是唯一的。现在,我在我的应用程序中使用了一个简单的基于数组的索引,以防止将重复的电子邮件添加到批处理中。
我正在使用Node.js
和Sequelize
和Knex
编写我的应用,但是,具体技术在这里并不重要。
答案 0 :(得分:0)
pgAdmin具有自1.16以来的数据导入GUI。您必须先创建表,然后才能轻松导入数据 - 只需右键单击表名并单击“导入”。