Введение

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

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

Параметр work_mem

Задаёт объём памяти, который будет использоваться для внутренних операций сортировки и хеш-таблиц, прежде чем будут задействованы временные файлы на диске. Значение по умолчанию — 4 MB.

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

Если памяти недостаточно, PostgreSQL начинает использовать диск, что замедляет процесс.

Как использовать:

  • Для запросов с сортировкой (`ORDER BY`, `DISTINCT`) или группировкой (`GROUP BY`) можно временно увеличить значение: 

SET work_mem = '64MB';

  • Настраивайте это значение в зависимости от сложности запросов и доступной памяти.

effective_cache_size

Определяет представление планировщика об эффективном размере дискового кеша, доступном для одного запроса. Это представление влияет на оценку стоимости использования индекса; чем выше это значение, тем больше вероятность, что будет применяться сканирование по индексу, чем ниже, тем более вероятно, что будет выбрано последовательное сканирование. 

Значение этого параметра по умолчанию — 4 GB.

Как использовать:

  • Устанавливайте значение в диапазоне 50-75% от объёма оперативной памяти сервера.

  • Это помогает оптимизатору более эффективно выбирать индексное сканирование вместо последовательного чтения.

Этот запрос показывает процент успешных попаданий в кэш базы данных (cache hit ratio). Если значение ниже 90%:

SELECT sum(blks_hit) / (sum(blks_hit) + sum(blks_read)) * 100 AS cache_hit_ratio

FROM pg_stat_database;

Это сигнал, что можно увеличить параметр effective_cache_size. Также, возможно, ваши запросы слишком часто обращаются к диску, что замедляет выполнение. В таком случае можно рассмотреть увеличение shared_buffers для большего объема кэша.

Парметр shared_buffers

Определяет объём памяти, выделяемой PostgreSQL для хранения данных, которые часто запрашиваются. Этот параметр напрямую влияет на производительность чтения, так как данные из буфера читаются быстрее, чем с диска.

Как использовать:

  • Рекомендуется установить значение, равное 25-40% от общей оперативной памяти сервера. Например, если у сервера 16 ГБ ОЗУ, имеет смысл выделить под shared_buffers от 4 до 6 ГБ.

  • Мониторьте использование буфера с помощью метрик pg_stat_activity и pg_stat_database, чтобы убедиться, что данные действительно кэшируются эффективно.

  • Увеличение shared_buffers полезно для серверов, обрабатывающих большое количество однотипных запросов.

Рекомендации:

Не следует выделять более 50% памяти под shared_buffers, чтобы избежать нехватки ресурсов для других процессов. В сочетании с effective_cache_size и индексацией можно добиться значительного ускорения запросов.

Параметр random_page_cost

Задаёт стоимость случайного чтения данных с диска относительно последовательного чтения. Значение по умолчанию равно 4.0. Если вы считаете, что для вашей рабочей нагрузки процент попаданий не достигает 90%, вы можете увеличить параметр random_page_cost, чтобы он больше соответствовал реальной стоимости произвольного чтения. И напротив, если ваши данные могут полностью поместиться в кеше, например, когда размер базы меньше общего объёма памяти сервера, может иметь смысл уменьшить random_page_cost.

Как использовать:

  • Для серверов с SSD уменьшите значение до 1.1-1.5, чтобы оптимизатор активнее использовал индексы.

  • Для серверов с HDD используйте значение по умолчанию - 4.0.

Параметр default_statistics_target

Определяет объём статистики, собираемой для таблиц и индексов. Чем выше значение, тем точнее оптимизатор предсказывает объёмы данных и строит планы выполнения. Значение этого параметра по умолчанию — 100. Чем больше установленное значение, тем больше времени требуется для выполнения ANALYZE, но тем выше может быть качество оценок планировщика.

Как использовать:

  • Для таблиц с часто изменяющимися данными увеличьте значение:

ALTER TABLE your_table SET (statistics_target = 200);

Параметры enable_hashjoin , enable_mergejoin, enable_nestloop

Параметры контролируют использование различных типов соединений.

enable_hashjoin: позволяет использовать хэш-соединения (hash join). Они эффективны при работе с большими наборами данных, где используется условие равенства (=) для объединения. Хэш-соединения хорошо подходят для запросов с большими таблицами, где одна из них может быть полностью загружена в память.

enable_mergejoin: позволяет использовать соединения слиянием (merge join). Эти соединения эффективны для предварительно отсортированных данных и отлично работают, если обе таблицы отсортированы по ключам соединения. Они также подходят для диапазонных условий (BETWEEN, >=, <=).

enable_nestloop: разрешает использование вложенных циклов (nested loop join). Этот тип соединения подходит для небольших таблиц или в случаях, когда индекс позволяет быстро находить соответствия. Однако при работе с большими таблицами или без индексов он может стать узким местом из-за большого количества итераций.

Как использовать:

  • Используйте для диагностики и анализа планов выполнения запросов.

  • Для сложных запросов временно отключайте, например:

SET enable_nestloop = off;

Советы

Настройка параметров требует осторожности и учета специфики вашего приложения и инфраструктуры. Вот несколько ключевых моментов:

Осторожность в настройках:

  • Не задавайте слишком высокие значения для параметров, таких как work_mem, чтобы избежать нехватки памяти.

  • Тестируйте изменения параметров в изолированной среде перед их применением на рабочем сервере.

Мониторинг:

  • Используйте встроенные инструменты PostgreSQL, такие как pg_stat_activity и pg_stat_statements, для анализа запросов.

  • Настройте системы мониторинга (например, Prometheus или Zabbix), чтобы отслеживать производительность базы данных.

Заключение

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

При всех возможностях ручной настройки PostgreSQL, управление инфраструктурой и мониторинг требуют времени и ресурсов. Здесь на помощь приходит модель Database-as-a-Service (DBaaS). Использование DBaaS позволяет:

  • Сосредоточиться на разработке. Вам не нужно заниматься настройкой серверов, установкой обновлений или конфигурацией — всё это выполняется автоматически.

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

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

  • Минимизировать риски. Регулярные резервные копии и высокая доступность гарантируют, что ваши данные защищены.

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

Если тема баз данных в облаке для вас актуальна, приходите на наш вебинар 26 ноября в 11:00, где мы продемонстрируем развертывание и интерфейс сервиса DBaaS на основе PostgreSQL, а также расскажем о совместной работе с сервисом Kubernetes в облаке Linx Cloud.

ЗАРЕГИСТРИРОВАТЬСЯ

Комментарии (5)


  1. Akina
    18.11.2024 13:07

    effective_cache_size - 50-75% от объёма оперативной памяти сервера

    shared_buffers - 25-40% от объёма оперативной памяти сервера

    Во-первых, что в данном случае "оперативная память сервера"? PostgreSQL не в вакууме работает, под ним ОС, рядом, возможно, ещё какие-то сервисы и приложения, они тоже памяти хотят - их учитывать будем? Или на них наплевать, считаем от физической памяти, и пусть крутятся, как хотят...

    Во-вторых, если размахнуться в обоих параметрах, то сумма превысит объём оперативной памяти сервера. Что, скорее всего, окончится фатально... а какой предел у этой суммы? и да, с учётом упомянутого в "во-первых"... А ещё - как определить, что мы таки хапнули лишнего?


    1. Linx Автор
      18.11.2024 13:07

      Абсолютно верно, PostgreSQL не работает изолированно, и на сервере могут быть другие сервисы и приложения, которые также требуют оперативной памяти. Под "оперативной памятью сервера" подразумевали доступный пул физической памяти, из которого ресурсы выделяются для всех процессов.

      Да, при настройке параметров необходимо учитывать:

      1. ОС: она использует часть оперативной памяти для своих нужд, включая файловый кэш.

      2. Другие приложения: если сервер используется не только для PostgreSQL, но и для других сервисов.

      3. Резерв: всегда стоит оставлять запас оперативной памяти для непредвиденных нагрузок или системных процессов.

      Таким образом, расчёт значений shared_buffers и effective_cache_size лучше производить от доступной памяти, остающейся после учёта всех прочих сервисов и ОС.


      1. Akina
        18.11.2024 13:07

        У вас тоже есть привычка отвечать исключительно на самый первый вопрос? ну я не гордый, повторю:

        как определить, что мы таки хапнули лишнего?

        Ну или в подробностях - как, по каким показателям или иным (каким?) признакам можно определить, что суммарный объём запрошенной настройками оперативной памяти превышает возможности системы по её выделению? Причём как признакам в ОС (и Windows, и Linux), так и в самом PostgreSQL.

        И если такое превышение выявлено - как корректировать настройки. Что их надо уменьшать - очевидно, но какую настройку надо снижать в первую очередь, насколько и почему именно её? какую корреляцию между значениями (например, их соотношение или разность) выдерживать, и опять же почему?


      1. pustoshilov_d
        18.11.2024 13:07

        Ммм абстрактный ответ из chatGPT

        Хотя вопрос важный поддерживаю! Но видимо единственный ответ на него это постоянный мониторинг nodeStats


  1. oller
    18.11.2024 13:07

    Просьба писать что-то новое, а не то что миллион раз расписано на habr в более подробных инструкциях