Советы по производительности Postgres Загрузка в миллиардах строк - PullRequest
3 голосов
/ 11 февраля 2011

Я нахожусь в середине проекта, включающего попытку извлечения многочисленных фрагментов информации из документов XML объемом 70 ГБ и загрузки ее в реляционную базу данных (в данном случае postgres). В настоящее время я использую для этого скрипты Python и psycopg2. вставки и еще много чего. Я обнаружил, что по мере увеличения количества строк в некоторых таблицах. (Самый большой из которых находится в пределах 5 миллионов строк). Скорость сценария (вставки) замедлилась до ползания. То, что раньше занимало пару минут, теперь занимает около часа.

Что я могу сделать, чтобы ускорить это? Был ли я неправ в использовании python и psycopg2 для этой задачи? Могу ли я что-нибудь сделать с базой данных, что может ускорить этот процесс. У меня такое ощущение, что я делаю это совершенно неправильно.

Ответы [ 7 ]

1 голос
/ 11 февраля 2011

Учитывая, что процесс был довольно эффективным, и только теперь, когда набор данных вырос, он замедлился, я думаю, что это индексы. Вы можете попробовать сбросить индексы в таблице перед импортом и воссоздать их после того, как это будет сделано. Это должно ускорить процесс.

1 голос
/ 11 февраля 2011

Какие настройки для wal_buffers и checkpoint_segments?Для больших транзакций вы должны настроить некоторые параметры.Проверьте руководство .

Также рассмотрите книгу Высокая производительность PostgreSQL 9.0 , есть гораздо больше настроек, чем просто конфигурация базы данных, чтобы получить высокую производительность.

0 голосов
/ 01 марта 2013

Первые 5 мил строк - ничто, разница во вставках не должна меняться - 100к или 1 мил; 1-2 индекса не будут сильно его тормозить (если коэффициент заполнения установлен на 70-90, учитывая, что каждый основной импорт составляет 1/10 таблицы).

Python с PSYCOPG2 довольно быстрый. Небольшой совет: вы можете использовать расширение базы данных XML2 для чтения / работы с данными

маленький пример из https://dba.stackexchange.com/questions/8172/sql-to-read-xml-from-file-into-postgresql-database

Даффимо правильно, попробуйте фиксировать кусками по 10000 вставок (фиксация только в конце или после каждой вставки довольно дорого) autovacuum может вздутие живота, если вы делаете много удалений и обновлений, вы можете отключить его временно при запуске для некоторых таблиц. установите work_mem и maintenance_work_mem в соответствии с доступными ресурсами ваших серверов ... для вставок увеличьте wal_buffers, (9.0 и выше по умолчанию установлено автоматически -1), если вы используете postgresql версии 8, вы должны увеличить его вручную cud также отключает fsync и тестирует wal_sync_method (будьте осторожны, изменяя это, вы можете сделать сбой вашей базы данных небезопасным, если произойдет внезапный сбой питания или сбой оборудования)

попытаться сбросить внешние ключи, отключить триггеры или задать условия, чтобы триггер не запускал / пропускал выполнение;

использовать подготовленные операторы для вставок, приведение переменных

вы можете попытаться вставить данные в незафиксированную таблицу для временного хранения данных

вставки имеют где условия или значения из подзапроса, функции или тому подобное?

0 голосов
/ 15 февраля 2011

Список подсказок по этой теме содержится в разделе Заполнение базы данных документации. Вы можете повысить общую производительность, используя подсказки в Настройка сервера PostgreSQL .

Затраты на проверку внешних ключей могут увеличиваться при увеличении размера таблицы, что ухудшается из-за загрузки по одной записи за раз. Если вы загружаете данные объемом 70 ГБ, гораздо быстрее будет отбрасывать внешние ключи во время загрузки, а затем перестраивать их при импорте. Это особенно верно, если вы используете отдельные операторы INSERT. Переключение на COPY вместо этого также не является гарантированным улучшением из-за того, как обрабатывается очередь отложенных триггеров - проблемы, которые обсуждаются в этой первой ссылке на документацию.

В приглашении psql вы можете найти имя ограничения, применяющего ваш внешний ключ, а затем удалить его, используя это имя, например:

\d tablename
ALTER TABLE tablename DROP CONSTRAINT constraint_name;

Когда вы закончите загрузку, вы можете положить ее обратно, используя что-то вроде:

ALTER TABLE tablename ADD CONSTRAINT constraint_name FOREIGN KEY (other_table) REFERENCES other_table (join_column);

Один полезный трюк, чтобы выяснить точный синтаксис, который нужно использовать для восстановления, - это сделать pgdump --schema-only в вашей базе данных. Из этого дампа вы узнаете, как воссоздать структуру, которая у вас есть сейчас.

0 голосов
/ 13 февраля 2011
0 голосов
/ 11 февраля 2011

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

Проверьте, все ли внешние ключи из этой таблицы имеют соответствующий индекс для целевой таблицы. Или лучше - временно удалите их перед копированием и создайте заново после.

Увеличьте checkpoint_segments со значения по умолчанию 3 (что означает 3 * 16 МБ = 48 МБ) до гораздо большего числа - попробуйте, например, 32 (512 МБ). убедитесь, что у вас достаточно места для этих дополнительных данных.

Если вы можете позволить себе воссоздать или восстановить кластер базы данных с нуля в случае сбоя системы или сбоя питания, вы можете запустить Postgres с опцией -F, которая включит кэш записи ОС.

0 голосов
/ 11 февраля 2011

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

Если это так, возможно, вы можете попробовать совершить транзакцию меньшего размера. Разделите его на меньшие блоки записей (1K, 10K, 100K и т. Д.) И посмотрите, поможет ли это.

...