Оптимизация PostgreSQL для быстрого тестирования


я переключаюсь на PostgreSQL из SQLite для типичного приложения Rails.

проблема в том, что запуск спецификаций стал медленным с PG.
На SQLite это заняло ~34 секунды, на PG это ~76 секунд, что более чем в 2 раза медленнее.

Итак, теперь я хочу применить некоторые методы, чтобы приведите производительность спецификаций наравне с SQLite без изменений кода (в идеале, просто установив параметры подключения, что, вероятно, нет вероятный.)

пара очевидных вещей с моей головы:

  • RAM диск (хорошая настройка с RSpec на OSX было бы хорошо видеть)
  • Незаписанные таблицы (можно ли применить его ко всей базе данных, чтобы у меня не было изменения всех скриптов?)

Как вы, возможно, поняли, я не забочусь о надежности и остальном (БД-это просто выброшенная вещь здесь).
Мне нужно получить максимальную отдачу от PG и сделать его так же быстро, как это может быть.

лучший ответ идеально описал бы хитрости для того, чтобы сделать именно это, настройка и недостатки этих трюков.

обновление:fsync = off + full_page_writes = off только уменьшенное время до ~65 секунд (~-16 секунд). Хорошее начало, но далеко от цели 34.

обновление 2: Я пробовал использовать RAM диск но прирост производительности в пределах погрешности. Так не кажется стоит того.

обновление 3:* Я нашел самое большое узкое место, и теперь мои спецификации работают так же быстро, как и SQLite.

проблема была очистка базы данных, что делал усечение. По-видимому, SQLite слишком быстро там.

чтобы "исправить" его я открываю сделки перед каждым тестом и откатить его в конце.

некоторые числа для ~700 тестов.

  • усечение: SQLite-34s, PG - 76Т.
  • транзакция: SQLite-17s, PG-18s.

2x увеличение скорости для SQLite. 4X увеличение скорости для PG.

2 179

2 ответа:

во-первых, всегда используйте последнюю версию PostgreSQL. Улучшения производительности всегда приходят, так что вы, вероятно, тратите свое время, если вы настраиваете старую версию. Например, PostgreSQL 9.2 значительно улучшает скорость TRUNCATE и, конечно, добавляет только индекс сканирования. Даже незначительные релизы должны всегда следовать; см. версия политики.

запреты

Do не поместите табличное пространство на a Электронный диск или другие недлительного хранения.

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

если вы действительно хотите систему на основе ramdisk,initdb целый новый кластер на ramdisk by initdbing новый экземпляр PostgreSQL на ramdisk, поэтому у вас есть полностью одноразовый PostgreSQL пример.

конфигурация сервера 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 и получить реальный прирост скорости за счет получения таблиц стирается в случае сбоя сервера. Там нет опции конфигурации, чтобы сделать все таблицы unlogged, он должен быть установлен во время CREATE TABLE. В дополнение к хорошему тестированию это удобно, если у вас есть таблицы, полные сгенерированных или неважных данных в базе данных, которая в противном случае содержит материал, который вам нужно быть в безопасности.

проверить логи и посмотреть, если вы получаете предупреждения о слишком много контрольно-пропускных пунктов. Если да, то вы должны увеличить свой checkpoint_segments. Вы также можете настроить ваш checkpoint_completion_target для сглаживания записывает.

настройки shared_buffers чтобы соответствовать вашей работы. Это зависит от ОС, зависит от того, что еще происходит с вашей машиной, и требует некоторых проб и ошибок. Значения по умолчанию крайне консервативны. Возможно, Вам потребуется увеличить максимальный предел общей памяти ОС, если вы увеличите shared_buffers на PostgreSQL 9.2 и ниже; 9.3 и выше изменилась, как они используют общую память, чтобы избежать этого.

если вы используете только пару соединения, которые делают много работы, увеличить work_mem чтобы дать им больше оперативной памяти, чтобы играть с для сортов и т. д. Помните, что слишком высокая work_mem установка может вызвать проблемы с памятью, потому что это за сортировку, а не за соединение, поэтому один запрос может иметь много вложенных сортов. Ты только действительно увеличить 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 модуль для отчета обо всех медленных запросах. Часто можно значительно повысить производительность запросов, просто создав соответствующий индекс или изменив параметры затрат.

насколько мне известно, нет никакого способа, чтобы установить всю базу данных или кластер как UNLOGGED. Было бы интересно сделать это. Рассмотрите возможность запроса в списке рассылки PostgreSQL.

настройка ОС хоста

есть некоторые настройки, которые вы можете сделать на уровне операционной системы, тоже. Главное, что вы можете сделать, это убедить операционную систему не сбрасывать записи на диск агрессивно, так как вам действительно все равно, когда/если они попадут на диск.

в Linux вы можете управлять этим с помощью подсистема виртуальной памяти ' s dirty_* настройки, как dirty_writeback_centisecs.

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

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

на новых ядрах вы можете убедиться, что vm.zone_reclaim_mode устанавливается в ноль, как это может вызвать серьезные проблемы с производительностью систем NUMA (большинство систем в эти дни) из-за взаимодействия с тем, как PostgreSQL управляет shared_buffers.

настройка запросов и рабочей нагрузки

это вещи, которые не требуют изменения кода; они могут не подойти вам. Некоторые вещи вы могли бы быть в состоянии применить.

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

по возможности используйте временные таблицы. Они не генерируют трафик WAL, поэтому они намного быстрее для вставок и обновлений. Иногда стоит прихлебывать кучу данных в временную таблицу, манипулируя ею, как вам нужно, а затем делать INSERT INTO ... SELECT ... чтобы скопировать его в финальную таблицу. Обратите внимание, что временные таблицы за сеанс; если сеанс заканчивается или вы теряете соединение, то временная таблица исчезает, и никакое другое соединение не может видеть содержимое временных таблиц сеанса.

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

в общем, не DELETE FROM blah;. Используйте TRUNCATE TABLE blah; вместо этого; это намного быстрее, когда вы сбрасываете все строки в таблице. Усечь много таблиц в одном TRUNCATE позвоните, если сможете. Есть один нюанс, если вы делаете много TRUNCATES маленьких столов снова и снова, хотя; см.: скорость усечения Postgresql

если у вас нет индексов на внешние ключи, DELETES с участием первичных ключей, на которые ссылаются эти внешние ключи будут ужасно медленно. Не забудьте создать такие индексы, если вы когда-либо ожидали DELETE из таблицы (таблиц) ссылок. Индексы не требуются для TRUNCATE.

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

оборудование

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

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

обучение

книга Грега Смита, PostgreSQL 9.0 High Производительность остается актуальным, несмотря на ссылку на несколько более старую версию. Он должен быть полезным.

Присоединяйтесь к общему списку рассылки PostgreSQL и следуйте ему.

читать:

используйте другую раскладку диска:

  • другой диск для $PGDATA
  • другой диск для $PGDATA / pg_xlog
  • другой диск для файлов tem (для каждой базы данных $PGDATA / base//pgsql_tmp) (см. Примечание о work_mem)

postgresql.conf tweaks:

  • shared_memory: 30% доступной оперативной памяти, но не более 6 до 8 ГБ. Кажется, лучше иметь меньше общей памяти (2 ГБ - 4 ГБ) для интенсивной записи рабочие нагрузки
  • work_mem: в основном для запросов select с сортировкой/агрегацией. Это для каждого параметра подключения, и запрос может выделить это значение несколько раз. Если данные не могут поместиться, то используется диск (pgsql_tmp). Проверьте "объяснить анализ", чтобы увидеть, сколько памяти вам нужно
  • fsync и synchronous_commit: значения по умолчанию безопасны, но если вы можете допустить потерю данных, то вы можете отключить
  • random_page_cost: если у вас есть SSD или быстрый массив RAID, вы можете снизить это до 2.0 (RAID) или даже ниже (1.1) для SSD
  • checkpoint_segments: вы можете пойти выше 32 или 64 и изменить checkpoint_completion_target на 0.9. Более низкое значение позволяет быстрее восстановить после аварии