Введение
Оптимизация запросов в 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)
oller
18.11.2024 13:07Просьба писать что-то новое, а не то что миллион раз расписано на habr в более подробных инструкциях
Akina
Во-первых, что в данном случае "оперативная память сервера"? PostgreSQL не в вакууме работает, под ним ОС, рядом, возможно, ещё какие-то сервисы и приложения, они тоже памяти хотят - их учитывать будем? Или на них наплевать, считаем от физической памяти, и пусть крутятся, как хотят...
Во-вторых, если размахнуться в обоих параметрах, то сумма превысит объём оперативной памяти сервера. Что, скорее всего, окончится фатально... а какой предел у этой суммы? и да, с учётом упомянутого в "во-первых"... А ещё - как определить, что мы таки хапнули лишнего?
Linx Автор
Абсолютно верно, PostgreSQL не работает изолированно, и на сервере могут быть другие сервисы и приложения, которые также требуют оперативной памяти. Под "оперативной памятью сервера" подразумевали доступный пул физической памяти, из которого ресурсы выделяются для всех процессов.
Да, при настройке параметров необходимо учитывать:
ОС: она использует часть оперативной памяти для своих нужд, включая файловый кэш.
Другие приложения: если сервер используется не только для PostgreSQL, но и для других сервисов.
Резерв: всегда стоит оставлять запас оперативной памяти для непредвиденных нагрузок или системных процессов.
Таким образом, расчёт значений shared_buffers и effective_cache_size лучше производить от доступной памяти, остающейся после учёта всех прочих сервисов и ОС.
Akina
У вас тоже есть привычка отвечать исключительно на самый первый вопрос? ну я не гордый, повторю:
Ну или в подробностях - как, по каким показателям или иным (каким?) признакам можно определить, что суммарный объём запрошенной настройками оперативной памяти превышает возможности системы по её выделению? Причём как признакам в ОС (и Windows, и Linux), так и в самом PostgreSQL.
И если такое превышение выявлено - как корректировать настройки. Что их надо уменьшать - очевидно, но какую настройку надо снижать в первую очередь, насколько и почему именно её? какую корреляцию между значениями (например, их соотношение или разность) выдерживать, и опять же почему?
pustoshilov_d
Ммм абстрактный ответ из chatGPT
Хотя вопрос важный поддерживаю! Но видимо единственный ответ на него это постоянный мониторинг nodeStats