Оптимизация вставок Postgres - PullRequest
       20

Оптимизация вставок Postgres

6 голосов
/ 03 декабря 2010

У меня есть скрипт, который генерирует десятки тысяч вставок в базу данных postgres через пользовательский ORM. Как вы можете себе представить, это довольно медленно. Это используется в целях разработки для создания фиктивных данных. Есть ли простая оптимизация, которую я могу сделать на уровне Postgres, чтобы сделать это быстрее? Это единственный скрипт, работающий последовательно и не требующий безопасности потоков.

Возможно, я смогу отключить все блокировки, проверки безопасности, триггеры и т. Д.? Просто ищу быстрое и грязное решение, которое значительно ускорит этот процесс.

Спасибо.

Ответы [ 7 ]

8 голосов
/ 04 декабря 2010

Если вам не нужна такая функциональность в производственной среде, я бы посоветовал вам отключить fsync из конфигурации PostgreSQLЭто значительно ускорит вставки.

Никогда не отключайте fsync в производственной базе данных.

8 голосов
/ 03 декабря 2010

Самый быстрый способ вставить данные - это команда COPY. Но для этого требуется плоский файл в качестве входных данных. Я думаю, что создание плоского файла не вариант.

Не фиксируйте слишком часто, особенно , а не запускайте это с включенной автоматической фиксацией. «Десятки тысяч» звучат так, будто один конец в конце будет правильным.

Если вы можете посоветовать вашему ORM использовать многорядную вставку Postgres, которая также ускорит процесс

Это пример многострочной вставки:

insert into my_table (col1, col2) 
values 
(row_1_col_value1, row_1_col_value_2), 
(row_2_col_value1, row_2_col_value_2), 
(row_3_col_value1, row_3_col_value_2)

Если вы не можете сгенерировать приведенный выше синтаксис и используете Java, убедитесь, что вы используете пакетные операторы вместо вставок одного оператора (возможно, другие уровни БД допускают нечто подобное)

Редактировать:

Пост

jmz вдохновил меня на добавление:

Вы также можете увидеть улучшение при увеличении wal_buffers до некоторого большего значения (например, 8 МБ) и checkpoint_segments (например, 16)

6 голосов
/ 05 декабря 2010

Для вставок с этим числом от сотен до тысяч, пакетируйте их:

begin;
insert1 ...
insert2 ...
...
insert10k ... 
commit;

Для вставок в миллионах используйте копию:

COPY test (ts) FROM stdin;
2010-11-29 22:32:01.383741-07
2010-11-29 22:32:01.737722-07
... 1Million rows
\.

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

3 голосов
/ 03 декабря 2010

Одна вещь, которую вы можете сделать, это удалить все индексы, выполнить вставки, а затем воссоздать индексы.

2 голосов
/ 07 июня 2013

Попробуйте сделать как можно больше за один запрос!

insert into my_table (col1, col2) 
values (
  unnest(array[row_1_col_value_1, row_2_col_value_1, row3_col_value_1]), 
  unnest(array[row_1_col_value_2, row_2_col_value_2, row_3_col_value_2));

Это напоминает предложение @a_horse_with_no_name. Преимущество использования unnest заключается в следующем: вы можете использовать параметры запроса, содержащие массивы!

insert into my_table (col1, col2) 
values (unnest(:col_values_1), unnest(:col_values_2));

Объединяя три оператора insert в один, вы экономите более 50% времени выполнения. И используя параметры запроса с 2000 значениями в одном Insert, я получаю коэффициент скорости 150 в моем приложении.

2 голосов
/ 05 декабря 2010

Если вы только инициализируете постоянные тестовые данные, вы также можете поместить тестовые данные в промежуточную таблицу (таблицы), а затем просто скопировать содержимое таблицы, используя

INSERT INTO... SELECT...

, что должно быть примерно так же быстрокак использование COPY (хотя я не тестировал его), с тем преимуществом, что вы можете копировать, используя только команды SQL, без хлопот настройки внешнего файла, как для COPY.

2 голосов
/ 03 декабря 2010

Вы отправляете партию из десятков тысяч вкладок ИЛИ отправляете десятки тысяч вкладок?

Я знаю, что с помощью Hibernate вы можете объединить все свои операторы SQL и отправить их в конце в один большой кусок вместо того, чтобы тратить накладные расходы сети и базы данных на создание тысяч операторов SQL по отдельности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...