Оптимизируйте PostgreSQL для быстрого тестирования - PullRequest
193 голосов
/ 23 февраля 2012

Я перехожу на PostgreSQL из SQLite для типичного приложения на Rails.

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

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

Несколько очевидных вещей из головы:

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

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

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

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

ОБНОВЛЕНИЕ 2: Я пытался использовать RAM диск , но прирост производительности был в пределах ошибки. Так что, похоже, оно того не стоит.

ОБНОВЛЕНИЕ 3: * Я нашел самое узкое место, и теперь мои спецификации работают так же быстро, как и спецификации SQLite.

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

Чтобы «исправить» это, я открываю транзакцию перед каждым тестом и откатываю ее в конце.

Некоторые цифры для ~ 700 тестов.

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

2-кратное увеличение скорости для SQLite. Увеличение скорости в 4 раза для PG.

Ответы [ 2 ]

267 голосов
/ 23 февраля 2012

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

Не следует

Не НЕ помещать табличное пространство на RAM-диск или другое недолговечное хранилище .

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

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

Конфигурация сервера PostgreSQL

При тестировании вы можете настроить свой сервер на недолговечныйно более быстрая работа .

Это одно из приемлемых вариантов использования fsync=off в PostgreSQL.Этот параметр в значительной степени указывает PostgreSQL не беспокоиться об упорядоченных записях или каких-либо других неприятных средствах защиты целостности данных и безопасности при сбоях, что позволяет ему полностью уничтожить ваши данные в случае потери питания или сбоя ОС.

Излишне говорить, что вы никогда не должны включать fsync=off в рабочей среде, если только вы не используете Pg в качестве временной базы данных для данных, которые вы можете повторно генерировать из других источников.Если и только если вы делаете, чтобы выключить fsync, вы также можете отключить full_page_writes, так как это больше не приносит пользы.Помните, что fsync=off и full_page_writes применяются на уровне cluster , поэтому они влияют на все базы данных в вашем экземпляре PostgreSQL.

Для производственного использования вы можете использоватьsynchronous_commit=off и установите commit_delay, поскольку вы получите многие из тех же преимуществ, что и fsync=off, без огромного риска повреждения данных.У вас есть небольшое окно потери последних данных, если вы включите асинхронную фиксацию - но это все.

Если у вас есть возможность немного изменить DDL, вы также можете использовать UNLOGGED таблицы в Pg 9.1+полностью избежать регистрации в WAL и получить реальное повышение скорости за счет удаления таблиц в случае сбоя сервера.Для всех таблиц нет конфигурации, она должна быть установлена ​​во время 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, чтобы сообщить о всех медленных запросах. Зачастую вы можете значительно повысить производительность запросов, просто создав соответствующий индекс или изменив параметры стоимости.

AFAIK Нет способа установить всю базу данных или кластер как UNLOGGED. Было бы интересно сделать это. Подумайте об этом в списке рассылки PostgreSQL.

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

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

В Linux вы можете управлять этим с помощью подсистемы виртуальной памяти , например 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 Скорость усечения

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

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

Аппаратное обеспечение

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

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

Learning

Книга Грега Смита, Высокая производительность PostgreSQL 9.0 остаетсяактуальны, несмотря на ссылку на несколько более старую версию.Это должен быть полезный справочник.

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

Чтение:

9 голосов
/ 23 февраля 2012

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

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

postgresql.conf:

  • shared_memory: 30% доступной оперативной памяти, но не более 6–8 ГБ. Кажется, было бы лучше иметь меньше разделяемой памяти (2–4 ГБ) для интенсивных рабочих нагрузок при записи
  • work_mem: в основном для выборочных запросов с сортировками / агрегатами. Это для каждого параметра подключения, и запрос может распределять это значение несколько раз. Если данные не помещаются, используется диск (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. Более низкое значение обеспечивает более быстрое восстановление после сбоя
...