2016-03-19 11 views
0

У меня есть приложение, которое должно загружать данные из заданных пользователем CSV-файлов в таблицы базы данных PostgreSQL.Загрузить данные из CSV-файла в базу данных PostgreSQL

Структура CSV-файл очень прост:

name,email 
John Doe,[email protected] 
... 

В базе данных у меня есть три таблицы:

--------------- 
-- 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 запросов для каждого E-Mail. Очевидно, это было очень медленное решение, которое позволяло мне загружать ~ 4 тыс. Записей в минуту, но код был довольно простым и простым.

  • Теперь я читаю CSV-файл по строкам, но объединяю все электронные письма в партии из 1 000 элементов. Все запросы SELECT/INSERT производятся партиями с использованием конструкций SELECT id, email WHERE email IN ('...', '...', '...', ...). Такой подход повысил производительность, и теперь у меня производительность ~ 25 тыс. Записей в минуту. Однако для этого подхода потребовался довольно сложный многоэтапный код.

Есть ли какие-либо более эффективные подходы к решению этой проблемы и получить еще большую производительность?


Основной проблемой здесь является то, что мне нужно вставить данные в таблицу recipients первой, а затем мне нужно использовать сгенерированный id создать соответствующую запись в таблице submissions.

Кроме того, мне нужно убедиться, что вставленные E-Mail уникальны. Прямо сейчас, я использую простой индекс на основе массива в своем приложении, чтобы предотвратить добавление дубликатов E-Mails в пакет.

Я пишу свое приложение, используя Node.js и Sequelize с Knex, однако конкретная технология здесь не имеет значения.

+0

Загрузка данных в временную таблицу, а затем использовать любую функцию из SQL/PostgreSQL, что вам необходимо. – Abelisto

+2

Вы знакомы с командой COPY (http://www.postgresql.org/docs/9.5/static/sql-copy.html)? Переведите его во временную таблицу, а затем используйте свои вставки для заполнения таблиц назначения.(COPY не является стандартным SQL btw) –

+0

Использование 'COPY' - это самый быстрый способ. Смотрите: http://stackoverflow.com/questions/33271377/postgres-csv-copy-from-import-is-not-respecting-csv-headers –

ответ

0

pgAdmin имеет GUI для импорта данных с 1,16. Сначала вам нужно создать свою таблицу, а затем легко импортировать данные - просто щелкните правой кнопкой мыши имя таблицы и нажмите «Импорт».

enter image description here

enter image description here

+0

Я не могу использовать для этого какой-либо сторонний графический инструмент. Мне нужно сделать это через свое приложение или, по крайней мере, через какой-то API. –

Смежные вопросы