Postgres - массовая передача данных из одной таблицы в другую. - PullRequest
0 голосов
/ 11 сентября 2018

Мне нужно перенести большой объем данных (несколько миллионов строк) из одной таблицы в другую. До сих пор я пытался сделать это ...

INSERT INTO TABLE_A (field1, field2) 
SELECT field1, field2 FROM TABLE_A_20180807_BCK;

Это сработало (в конце концов) для таблицы с примерно 10 миллионами строк (заняло 24 часа). Проблема в том, что у меня есть несколько других таблиц, для которых требуется тот же процесс, и все они намного больше (самая большая - 20 миллионов строк). Я попытался выполнить аналогичную загрузку с таблицей, содержащей 12 миллионов строк, и она не была выполнена за 48 часов, поэтому мне пришлось отменить ее.

Другие проблемы, которые могут повлиять на производительность: 1) TABLE_A имеет поле на основе автоматически сгенерированной последовательности, 2) TABLE_A имеет триггер AFTER INSERT, который анализирует каждую новую запись и добавляет вторую запись в TABLE_B

Несколько других потоков предложили сделать pg_dump TABLE_A_20180807_BCK и затем загрузить данные обратно в TABLE_A. Я не уверен, что pg_dump действительно сработает для меня, потому что меня интересуют только пара полей из TABLE_A, а не вся партия.

Вместо этого я задавался вопросом о следующем ...

Экспорт в файл CSV… ..

COPY TABLE_A_20180807_BCK (field1,field2) to 'd:\tmp\dump\table_a.dump' DELIMITER ',' CSV;

Импорт обратно в нужную таблицу….

COPY TABLE_A(field1,field2) FROM 'd:\tmp\dump\table_a.dump' DELIMITER ',' CSV

Вероятно ли, что метод экспорта / импорта будет быстрее - мне хотелось бы получить некоторые рекомендации по этому вопросу, прежде чем я начну выполнять другую работу, которая может занять несколько дней, а может даже не работать лучше! Очевидный ответ «просто попробуй и посмотри» на самом деле не вариант, я не могу позволить себе больше простоев!

(это дополнительный вопрос от до , если требуется дополнительная информация)

Обновление .... Я не думаю, что есть какие-либо существенные проблемы с триггером. При нормальных обстоятельствах записи вводятся в TABLE_A со скоростью около 1000 / сек (включая время запуска). Я думаю, что проблема, вероятно, заключается в размере транзакции, при нормальных обстоятельствах записи вставляются в блоки по 100 записей на одну INSERT, приведенное выше утверждение пытается добавить 10 миллионов записей в одной транзакции, я предполагаю, что это проблема, но у меня нет возможности узнать, так ли это на самом деле, или есть подходящее решение (или если предложенный мной метод экспорта / импорта будет быстрее)

Возможно, мне следовало бы подчеркнуть это раньше, каждая вставка в TABLE_A запускает триггер, который добавляет запись в TABLE_B. Конечная цель - это данные в TABLE_B, поэтому отключение триггера не вариант! Вся эта проблема возникла потому, что я случайно отключил триггер на несколько дней, и предпочтительным решением вопроса «как запустить триггер на существующих строках» было «удалить строки и добавить их снова» - см. Оригинал пост (ссылка выше) для деталей.

Моя текущая попытка состоит в том, чтобы использовать команду COPY с предложением WHERE, чтобы разделить содержимое TABLE_A_20180807_BCK на дюжину маленьких файлов и затем загрузить их по одному за раз. Это может не дать мне никакой общей экономии времени, но хотя я не могу позволить себе 24 часа непрерывного простоя, я могу позволить себе 6 часов простоя на 4 ночи.

1 Ответ

0 голосов
/ 11 сентября 2018

Подготовка (если у вас есть доступ и вы можете перезапустить сервер), установите checkpoint_segments в 32 или, возможно, больше.Это уменьшит частоту и количество контрольных точек во время этой операции.Вы можете отменить это, когда вы закончите.Этот шаг не является абсолютно необходимым, но он должен значительно ускорить запись.

отредактируйте postgresql.conf и установите для checkpoint_segments значение 32 или больше

Шаг 1: удалите / удалите все индексы и триггеры в таблице A.

РЕДАКТИРОВАТЬ: Шаг 1a

alter table_a set unlogged;

(повторите шаг 1 для каждой таблицы, в которую вы вставляете)

Шаг 2. (необязательно, если вы делаете одну таблицу ввремя)

 begin transaction;

Шаг 3.

   INSERT INTO TABLE_A (field1, field2) 
   SELECT field1, field2 FROM TABLE_A_20180807_BCK;

(повторите шаг 3 для всех вставляемых таблиц)

Шаг 4. (необязательно, если вы это сделаететаблица за один раз)

 commit;

Шаг 5 повторно включает индексы и триггеры для всех таблиц.

Шаг 5a.

 Alter table_a set logged;
...