2010-12-03 3 views
6

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

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

Спасибо.

ответ

8

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

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

3

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

2

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

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

8

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

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

Если вы можете convice ваш ОРМ использовать многорядной вставки 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 убедитесь, что вы используете пакетные операторы вместо одиночных вставок заявления (возможно, и другие слои DB позволяют что-то подобное)

Edit:

Сообщение jmz 'вдохновило меня что-то добавить:

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

+0

+1 для КОПИРОВАНИЯ. Лучший подход к скорости. – karlgrz 2010-12-03 18:24:52

+1

Команда копирования НЕ требует плоского файла, так как она может принимать входные данные из стандартного входа. Сделайте резервную копию открытого текста для своего db, и вы увидите, что он содержит команды копирования с участием stdin. – 2010-12-05 12:34:20

6

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

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 
\. 

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

2

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

INSERT INTO... SELECT... 

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

2

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

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 в моем приложении.

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