Как массово вставлять только новые строки в PostreSQL

У меня есть список товаров (3 миллиона штук) без идентификаторов - только названия. Но я не знаю, какие названия уже существуют в БД. Новые товары (около 2,9 млн позиций) должны быть добавлены в БД. После этого я должен знать ID для каждого продукта (нового и существующего).

Есть ли самый быстрый способ сделать это в PostgreSQL? Я могу изменить БД по мере необходимости (добавить значения по умолчанию, добавить столбцы и т. д.).


person FireShock    schedule 05.04.2013    source источник


Ответы (1)


Импорт данных

COPY все в временную промежуточную таблицу и вставляйте в целевую таблицу только новые заголовки.

CREATE TEMP TABLE tmp(title text);

COPY tmp FROM 'path/to/file.csv';
ANALYZE tmp;

INSERT INTO tbl
SELECT DISTINCT tmp.title
FROM   tmp 
LEFT   JOIN tbl USING (title)
WHERE  tbl.title IS NULL;

Идентификаторы должны генерироваться автоматически с помощью столбца serial. tbl_id в tbl.

Конструкция LEFT JOIN / IS NULL дисквалифицирует уже существующие названия. NOT EXISTS было бы другой возможностью.

DISTINCT предотвращает дублирование входящих данных во временной таблице tmp.

ANALYZE помогает убедиться, что планировщик запросов выбирает разумный план. , а временные таблицы автоочисткой не анализируются.

Поскольку у вас есть 3 миллиона элементов, возможно, стоит повысить значение параметра temp_buffer (только для этого сеанса):

SET temp_buffers = 1000MB;

Или столько, сколько вы можете себе позволить и достаточно, чтобы держать временную таблицу в оперативной памяти, что намного быстрее. Примечание: это должно быть выполнено сначала в сеансе — до того, как будут созданы какие-либо временные объекты.

Получить идентификаторы

Чтобы просмотреть все идентификаторы импортированных данных:

SELECT tbl.tbl_id, tbl.title
FROM   tbl
JOIN   tmp USING (title)

В том же сеансе! Временная таблица удаляется автоматически в конце сеанса.

person Erwin Brandstetter    schedule 05.04.2013