Я перехожу к PostgreSQL из SQLite для типичного приложения Rails.
Проблема в том, что запущенные спецификации стали медленными с PG.
На SQLite потребовалось ~ 34 секунды, на PG - ~ 76 секунд, что больше, чем 2x медленнее.
Итак, теперь я хочу применить некоторые методы к , чтобы обеспечить производительность спецификаций на уровне SQLite без изменений кода (в идеале, просто установив параметры подключения, что, вероятно, невозможно).
Несколько очевидных вещей с головы:
Как вы, возможно, поняли, что меня не интересует надежность, а остальное (DB - всего лишь одноразовая вещь).
Мне нужно максимально использовать PG и сделать его настолько быстрым, насколько это возможно.
Лучший ответ идеально описывает трюки для этого, настройки и недостатки этих трюков.
UPDATE: fsync = off
+ full_page_writes = off
уменьшено время до ~ 65 секунд (~ -16 секунд). Хорошее начало, но далеко от цели 34.
ОБНОВЛЕНИЕ 2: я попытался использовать RAM-диск, но прирост производительности был в пределах ошибки. Так что, похоже, не стоит того.
ОБНОВЛЕНИЕ 3: * Я нашел самое узкое место, и теперь мои спецификации работают так же быстро, как SQLite.
Проблема заключалась в очистке базы данных, которая выполняла усечение. По-видимому, SQLite слишком быстро там.
Чтобы "исправить", я открываю транзакцию перед каждым тестом и откатываю ее в конце.
Некоторые номера для ~ 700 тестов.
2x увеличение скорости для SQLite. 4-кратное увеличение скорости для PG.
Во-первых, всегда используйте последнюю версию PostgreSQL. Улучшения производительности всегда наступают, поэтому вы, вероятно, тратите свое время, если настраиваете старую версию. Например, PostgreSQL 9.2 значительно улучшает скорость TRUNCATE
и, конечно же, добавляет только индексирование. Всегда следует соблюдать даже незначительные выпуски; см. в разделе политики .
НЕ помещайте табличное пространство в RAMdisk или другое не долговременное хранилище.
Если вы потеряете табличное пространство, вся база данных может быть повреждена и сложна в использовании без существенной работы. Для этого очень мало преимуществ по сравнению с использованием таблиц UNLOGGED
и в любом случае с большим количеством ОЗУ для кеша.
Если вам действительно нужна система на основе ramdisk, initdb
новый кластер в ramdisk initdb
с новым экземпляром PostgreSQL в ramdisk, поэтому у вас есть полностью одноразовый экземпляр PostgreSQL.
При тестировании вы можете настроить сервер для не долговечной, но более быстрой работы.
Это одно из единственно приемлемых применений для параметра fsync=off
в PostgreSQL. Этот параметр в значительной степени говорит PostgreSQL о том, что он не беспокоится о заказанной записи или какой-либо другой неприятной информации, защищающей целостность данных и безопасности при сбое, давая ему разрешение полностью уничтожать ваши данные, если вы потеряете питание или сбой ОС.
Излишне говорить, что вы никогда не должны включать fsync=off
в производство, если вы не используете Pg в качестве временной базы данных для данных, которые вы можете повторно генерировать из других источников. Если и только если вы делаете, чтобы отключить fsync, вы можете отключить full_page_writes
, так как это уже не так хорошо. Помните, что fsync=off
и full_page_writes
применяются на уровне кластера, поэтому они влияют на все базы данных в вашем экземпляре PostgreSQL.
Для использования в целях производства вы можете использовать synchronous_commit=off
и установить commit_delay
, так как вы получите много преимуществ, таких как fsync=off
без риска гибели данных. У вас есть небольшое окно с потерей последних данных, если вы активируете асинхронное комментирование, но это оно.
Если у вас есть возможность слегка изменить DDL, вы также можете использовать таблицы UNLOGGED
в Pg 9.1+, чтобы полностью исключить ведение журнала WAL и получить реальное ускорение скорости за счет стрижки таблиц, если сервер выйдет из строя. Не существует опции конфигурации, чтобы сделать все таблицы незаписанными, она должна быть установлена во время CREATE TABLE
. В дополнение к тому, чтобы быть хорошим для тестирования, это удобно, если у вас есть таблицы, заполненные сгенерированными или несущественными данными в базе данных, которые в остальном содержат вещи, которые вам нужны для безопасности.
Проверьте свои журналы и посмотрите, есть ли предупреждения о слишком большом количестве контрольных точек. Если да, вы должны увеличить checkpoint_segments. Вы также можете настроить свою контрольную точку_completion_target, чтобы сгладить записи.
Настройте shared_buffers
, чтобы соответствовать вашей рабочей нагрузке. Это зависит от ОС, зависит от того, что еще происходит с вашей машиной, и требует некоторых проб и ошибок. По умолчанию они крайне консервативны. Возможно, вам потребуется увеличить ограничение максимальной общей памяти ОС, если вы увеличите shared_buffers
на PostgreSQL 9.2 и ниже; 9.3 и выше изменили способ использования разделяемой памяти, чтобы избежать этого.
Если вы используете только пару подключений, которые выполняют большую работу, увеличьте work_mem
, чтобы дать им больше оперативной памяти для сортировки и т.д. Остерегайтесь того, что слишком высокий параметр work_mem
может привести к нарушению -memory, потому что он не сортируется для каждого соединения, поэтому один запрос может иметь много вложенных ролей. Вам действительно нужно увеличить work_mem
, если вы можете увидеть сортировку, разливающуюся на диск в EXPLAIN
, или войти в систему с параметром log_temp_files
(рекомендуется), но более высокое значение может также позволить Pg выбрать более разумные планы.
Как сказал еще один плакат, целесообразно поместить xlog и основные таблицы/индексы на отдельные жесткие диски, если это возможно. Отдельные разделы довольно бессмысленны, вам действительно нужны отдельные диски. Это разделение имеет гораздо меньшую выгоду, если вы работаете с fsync=off
и почти нет, если используете таблицы UNLOGGED
.
Наконец, настройте свои запросы. Убедитесь, что ваши random_page_cost
и seq_page_cost
отражают производительность вашей системы, убедитесь, что ваш effective_cache_size
верен и т.д. Используйте EXPLAIN (BUFFERS, ANALYZE)
для просмотра отдельных планов запросов и включите модуль auto_explain
, чтобы сообщать обо всех медленных запросах. Вы часто можете улучшить производительность запросов, просто создав соответствующий индекс или изменив параметры затрат.
AFAIK нет способа установить всю базу данных или кластер как UNLOGGED
. Было бы интересно уметь это делать. Рассмотрите вопрос о списке рассылки PostgreSQL.
Там есть какая-то настройка, которую вы можете сделать и на уровне операционной системы. Главное, что вы, возможно, захотите сделать, - убедить операционную систему не скрывать записи на диск агрессивно, так как вам действительно все равно, когда/если они попадают на диск.
В Linux вы можете управлять этим с помощью подсистемы виртуальной памяти dirty_*
, например dirty_writeback_centisecs
.
Единственная проблема с настройкой параметров обратной записи, которая должна быть слишком слабой, заключается в том, что сброс какой-либо другой программы может привести к потере всех накопленных буферов PostgreSQL, вызывая большие киоски, а все блокирует запись. Вы можете облегчить это, запустив PostgreSQL в другой файловой системе, но некоторые флеши могут быть уровнями уровня на уровне устройства или уровня хоста, а не на уровне файловой системы, поэтому вы не можете полагаться на это.
Эта настройка действительно требует игры с настройками, чтобы увидеть, что лучше всего подходит для вашей рабочей нагрузки.
В более новых ядрах вы можете убедиться, что vm.zone_reclaim_mode
установлено на ноль, так как это может вызвать серьезные проблемы с производительностью в системах NUMA (большинство систем в наши дни) из-за взаимодействия с тем, как PostgreSQL управляет shared_buffers
.
Это вещи, для которых требуются изменения кода; они могут вас не устраивать. Некоторые из них могут быть применены.
Если вы не планируете работу над большими транзакциями, запустите. Многие небольшие транзакции стоят дорого, поэтому вы должны периодически делиться материалами, когда это возможно и практично. Если вы используете async commit, это менее важно, но все же рекомендуется.
По возможности используйте временные таблицы. Они не генерируют WAL-трафик, поэтому они намного быстрее для вставок и обновлений. Иногда стоит засыпать кучу данных в временную таблицу, манипулируя ею, но вам нужно, а затем INSERT INTO ... SELECT ...
скопировать ее в финальную таблицу. Обратите внимание, что временные таблицы относятся к сеансу; если ваш сеанс заканчивается или вы теряете соединение, тогда временная таблица исчезает, и никакое другое соединение не может видеть содержимое таблицы (ов) временной сессии сеанса.
Если вы используете PostgreSQL 9.1 или новее, вы можете использовать таблицы UNLOGGED
для данных, которые вы можете позволить себе потерять, например состояние сеанса. Они видны на разных сеансах и сохраняются между соединениями. Они усекаются, если сервер отключается нечисто, поэтому они не могут использоваться ни для чего, что вы не можете воссоздать, но они отлично подходят для кэшей, материализованных представлений, таблиц состояний и т.д.
В общем случае не DELETE FROM blah;
. Вместо этого используйте TRUNCATE TABLE blah;
; это намного быстрее, когда вы сбрасываете все строки в таблице. Усекайте многие таблицы одним вызовом TRUNCATE
, если сможете. Там оговорка, если вы делаете много TRUNCATES
маленьких таблиц снова и снова, хотя; см. Скорость усечения Postgresql
Если у вас нет индексов для внешних ключей, DELETE
с участием первичных ключей, на которые ссылаются эти внешние ключи, будет ужасно медленным. Не забудьте создать такие индексы, если вы когда-либо ожидали DELETE
из ссылочной таблицы (таблиц). Индексы не требуются для TRUNCATE
.
Не создавайте индексы, которые вам не нужны. Каждый индекс имеет стоимость обслуживания. Попытайтесь использовать минимальный набор индексов и позволить сканирование растровых индексов сочетать их, а не поддерживать слишком много огромных, дорогостоящих многоколоночных индексов. Если требуются индексы, сначала попробуйте заполнить таблицу, а затем создайте индексы в конце.
Наличие достаточного количества ОЗУ для хранения всей базы данных - огромная победа, если вы можете управлять ею.
Если у вас недостаточно ОЗУ, тем быстрее вы сможете получить лучшее хранилище. Даже дешевый SSD делает огромную разницу в ржавчине. Не доверяйте дешевым SSD для производства, хотя они часто не являются аварийными и могут съесть ваши данные.
Книга Грега Смита, Высокая производительность PostgreSQL 9.0 остается актуальной, несмотря на несколько более старую версию. Это должно быть полезной ссылкой.
Присоединитесь к списку рассылки PostgreSQL и следуйте за ним.
fsync=off
, размещение pg_xlog на отдельном диске больше не улучшится.