Данная статья посвящена способам повышения производительности PostgreSQL и EDB Postgres Advanced Server (EPAS) с 10 по 13 версии. Мы начнём с аппаратного обеспечения и будем двигаться вверх по стеку, оставив напоследок SQL-запросы.  Примечание: детали настроек зависят от рабочей нагрузки. Мы даём общие рекомендации, которые станут неплохой отправной точкой для большинства развёртываний.  При проектировании «голого» сервера для PostgreSQL нужно учитывать несколько моментов: процессор, оперативную память и диск. Выбор подходящего процессора может оказаться решающим в производительности PostgreSQL. При работе с большими данными важна скорость, но размер кэша L3 тоже влияет на показатели производительности.  Что такое кэш L3? Процессоры имеют по крайней мере два кэша: L1 — кэш первого уровня, и L2 — кэш второго уровня. L1 считается самым маленьким и быстрым кэшем; L2 медленнее, но больше по размеру. В современных процессоров L1 и L2 присутствуют на самих ядрах, причём каждое ядро получает собственный кэш. L3 работает медленнее, чем L1 и L2, но является общим для всех доступных ядер.  Наличие кэша L3 повышает производительность процессора при работе с большим набором данных. Также это полезно для параллельных запросов PostgreSQL. Операционные системы используют доступную память и стараются кэшировать как можно больше данных. Увеличение объёма кэширования приводит к уменьшению объёма дисковых операций ввода-вывода и ускорению времени выполнения запросов. При покупке нового оборудования рекомендуем сразу добавлять как можно больше оперативной памяти, так как в будущем это будет стоить сильно дороже как с финансовой, так и с технической стороны. Если приложение связано с вводом-выводом (интенсивное чтение и /или запись), выбор более быстрого набора дисков значительно повысит производительность. Доступно множество решений, включая NMVe и SSD-накопители. Первое правило — отделить диск WAL от диска данных. WAL может оказаться узким местом в базах данных с интенсивной записью, а его хранение на отдельном и быстром диске решит проблему. Используйте RAID 1. Если база данных много пишет — RAID 10. Отдельные табличные пространства и диски для индексов также позволяют повысить производительность, особенно если PostgreSQL работает на SATA. Но для SSD и NVMe это обычно не требуется.  Сетевые карты не имеют прямого отношения к производительности PostgreSQL. Однако при значительном увеличении объёма данных более быстрые сетевые карты ускоряют резервное копирование базы данных. «PostgreSQL База» Есть несколько способов, как повысить производительность PostgreSQL в виртуальных машинах. Первый — закрепить виртуальную машину на определённых процессорах и дисках. Это устранит или ограничит узкие места в производительности, которые могут возникнуть из-за других виртуальных машин, работающих на хосте. Второй — предварительно выделить диски перед установкой. Это предотвратит выделение хостом дискового пространства во время операций с базой данных. Если вы не можете этого сделать, измените два параметра в postgresql.conf: Отключите параметр wal_recycle в postgresql.conf. По умолчанию при переработке PostgreSQL переименовывает файлы WAL. Однако в файловых системах с копированием при записи (COW) создание новых файлов WAL быстрее. Отключите параметр wal_init_zero в postgresql.conf. По умолчанию пространство WAL выделяется перед вставкой записей WAL. Это замедляет операции WAL в файловых системах COW. Отключение параметра приведёт к отключению этой функции, что позволит виртуальным машинам работать лучше. Если установлено значение off, при создании файла записывается только последний байт, чтобы он имел ожидаемый размер. Настройка операционной системы также даёт дополнительные возможности для повышения производительности PostgreSQL. В рамках этой статьи разбираем настройку PostgreSQL для семейства Red Hat Enterprise Linux (RHEL). Большая часть настройки RHEL выполняется с помощью демона tuned. Он адаптирует операционную систему, чтобы она лучше справлялась с рабочей нагрузкой. Примечание: показанные команды предназначены для RHEL 8. Для RHEL 7 нужно использовать команду yum везде, где в примерах указан dnf. Обычно демон tuned устанавливается по умолчанию. Если нет, установите его:  И включите: tuned позволяет системным администраторам легко и динамично менять настройки ядра. Больше не нужно вносить изменения в /etc/sysctl — всё делается с помощью tuned. tuned поставляется с несколькими предопределенными профилями. Вы можете получить список, используя: Установщик RHEL выбирает значение в зависимости от среды. По умолчанию используется «throughput-performance», целью которого — увеличение пропускной способности. Вы можете запустить следующую команду, чтобы посмотреть, что порекомендует tuned daemon после оценки вашей системы: Используйте эту команду, чтобы увидеть предварительно настроенное значение: Однако настройки по умолчанию способны в конечном счёте привести к замедлению работы PostgreSQL — они могут предпочесть энергосбережение, что спровоцирует замедление работы процессоров. Аналогичные аргументы справедливы и для настройки сети и ввода-вывода. Для решения этой проблемы мы создадим собственный профиль повышения производительности PostgreSQL. Сделать это довольно просто. Назовём профиль «edbpostgres» и запустим команды от имени root: Строки, включающие [ and ], называются «настроенными плагинами» и используются для взаимодействия с данной частью системы. Теперь рассмотрим параметры и значения: плагин [main] включает сводную информацию, а также может использоваться для включения значений из других настроенных профилей с помощью инструкций include. плагин [cpu] включает в себя настройки регулятора процессора и настройки мощности процессора. плагин [sysctl] включает значения, которые взаимодействуют с procfs. плагины [vm] и [bootloader] включают/отключают huge pages (плагин bootloader помогает взаимодействовать с параметрами командной строки GRUB). С помощью изменений мы стремимся достичь следующего: процессоры не перейдут в режимы энергосбережения, а PostgreSQL не пострадает от случайных падений производительности; ядро поможет Postgres очищать грязные страницы, уменьшая нагрузку на bgwriter и checkpointer; демон pdflush будет запускаться чаще; отключение временных меток TCP — хорошая практика, чтобы избежать всплесков, вызванных генерацией временных меток. Для внедрения изменений выполните эту команду: Полностью отключите huge pages: И перезагрузите систему: Ещё один аспект настройки — диски. PostgreSQL не полагается на метку времени доступа atime для файлов данных, поэтому их отключение сэкономит циклы процессора. Откройте /etc/fstab и добавьте noatime рядом со значением для диска, на котором хранятся данные PostgreSQL и файлы WAL: Активируйте его: По умолчанию размер страницы в Linux составляет 4 КБ. Стандартный инстанс PostgreSQL может выделить много гигабайт памяти, что в конечном счёте приведет к проблемам с производительностью даже при таком небольшом размере страницы. Кроме того, эти страницы будут фрагментированы, поэтому их использование для больших наборов данных потребует дополнительного времени для сопоставления. Включение huge pages в Linux повысит производительность PostgreSQL, так как он будет выделять большие блоки памяти вместе. Есть два аспекта настройки — конфигурация операционной системы и конфигурация PostgreSQL. Начнём с того, сколько huge pages необходимо вашей системе для PostgreSQL. Когда запускается инстанс PostgreSQL, postmaster создает файл с именем postmaster.pid file в $PGDATA. Вы можете найти pid основного процесса там: Теперь найдите VmPeak для этого инстанса: Совет: если используете более одного инстанса PostgreSQL на одном сервере, рассчитайте сумму всех значений VmPeak на следующем шаге. Подтвердим размер страницы: Подсчитаем количество huge pages, которые потребуются инстансу(ам): 8823028 / 2048 = 4308.12 Оптимальное количество huge pages чуть больше этого — совсем чуть-чуть. Если вы увеличите значение слишком сильно, процессы, которым нужны small pages и место в ОС, не запустятся. Это может привести к сбою загрузки операционной системы или сбою запуска других инстансов PostgreSQL на том же сервере. Отредактируем созданный файл tuning.conf и добавим строку в раздел [sysctl]: И запустим команду, чтобы включить новые настройки: Теперь можем установить: в postgresql.conf и перезапустить PostgreSQL. Также нужно убедиться, что после перезагрузки настроенная служба запустится раньше, чем служба PostgreSQL. Отредактируем юнит-файл: И добавим две строки: Запустим, чтобы изменения вступили в силу: Оптимальное число для max_connections примерно в 4 раза превышает количество ядер CPU. Формула часто даёт небольшое число, которое не оставляет места для ошибки. Рекомендуемое число — GREATEST(4 x CPU cores, 100). Помимо этого следует использовать средство объединения подключений, например pgbouncer. Важно избегать установки слишком большого значения max_connections, так как это увеличит размер структур данных в Postgres, что может привести к потере циклов CPU. И наоборот: необходимо убедиться, что выделено достаточно ресурсов для поддержки требуемой рабочей нагрузки. Этот параметр имеет наибольшую дисперсию из всех. Некоторые рабочие нагрузки лучше всего работают с маленькими значениями (например, 1 ГБ или 2 ГБ) даже с внушительными объёмами базы данных. Другие рабочие нагрузки требуют больших значений. Оптимально — LEAST(RAM/2, 10GB). Для формулы нет конкретной причины, кроме многолетнего коллективного опыта сообщества PostgreSQL. Существуют сложные взаимодействия между кэшем ядра и shared_buffers, которые делают практически невозможным точное описание того, почему эта формула обычно даёт хорошие результаты. Рекомендуемое значение для  work_mem — ((Total RAM - shared_buffers)/(16 x CPU cores)). Логика формулы заключается в том, что если у вас так много запросов, что вы рискуете исчерпать память, вы автоматически привязаны к процессору.  Не следует устанавливать для work_mem более высокое значение, поскольку указанный объём памяти может использоваться каждым узлом в рамках одного плана запроса. Один запрос могут использовать в общей сложности несколько work_mem, например, во вложенной строке хэш-соединений. Определяет максимальный объём памяти, который используется для операций обслуживания (VACUUM, CREATE INDEX, ALTER TABLE ADD FOREIGN KEY) и операций загрузки данных. Может увеличивать объём операций ввода-вывода на серверах баз данных, поэтому выделение большего объёма памяти приводит к более быстрому завершению операций. Значение 1 ГБ — хорошее начало, поскольку это команды, которые явно выполняются администратором баз данных. Параметр используется для предварительного чтения во время определённых операций и должен быть установлен на количество дисков, задействованных для хранения данных. Изначально он предназначался, чтобы помочь Postgres понять, сколько чтений может происходить параллельно при использовании чередующихся RAID-массивов, но позже улучшения были отмечены использовании кратного этого числа. Вероятно, потому что RAID-адаптеры хорошего качества могут переупорядочивать и направлять запросы для повышения эффективности. Упреждающая журнализация Когда параметр включен, сервер PostgreSQL сжимает полностраничный образ, записываемый в WAL, при включённом параметре full_page_writes или во время базового резервного копирования. Установите для wal_compression значение «on», так как большинство серверов баз данных, скорее всего, будут ограничены вводом-выводом, а не процессором. Параметр необходим для использования pg_rewind. Включите его.   Определяет объём пространства, доступного серверным частям для записи данных WAL в память, чтобы затем WALWriter мог записать их в журнал WAL на диске в фоновом режиме. Сегменты WAL по умолчанию имеют размер 16 МБ каждый, поэтому буферизация сегмента обходится требует немного памяти. Отмечается, что большие размеры буфера потенциально оказывают положительное влияние на производительность при тестировании. Установите для этого параметра значение 64 МБ. Более длительные тайм-ауты уменьшают общий объём WAL, но увеличивают время восстановления после сбоя. Рекомендуемое значение — не менее 15 минут, но, в конечном счёте, бизнес-требования определяют, каким оно должно быть. Определяет количество времени, за которое PostgreSQL стремится выполнить контрольную точку. Контрольная точка не обязательно должна приводить к скачку ввода-вывода. Вместо этого она нацелена на распределение операций записи по части значения checkpoint_timeout. Рекомендуемое значение — 0.9. Контрольные точки всегда запускаются по тайм-ауту для повышения производительности и предсказуемости. Параметр max_wal_size следует использовать для защиты от нехватки места на диске. Рекомендуемое значение составляет от половины до двух третей доступного дискового пространства, на котором расположен WAL Для изменения этого параметра требуется перезагрузка, поэтому для него следует установить значение «on», если только вы не уверены, что никогда не будете использовать архивирование WAL. Если включен archive_mode, требуется команда archive_command. Пока архивирование не будет готово к настройке, предлагается значение по умолчанию 'to be configured'. Примитив ':' сообщает Postgres, что сегмент WAL может быть переработан или удалён.  to be configured — это набор аргументов, которые будут проигнорированы. Эти инструкции — хорошая отправная точка для большинства рабочих нагрузок OLTP. Мониторинг и корректировка перечисленных параметров нужны для получения максимальной производительности PostgreSQL для вашей рабочей нагрузки. В следующей части мы поговорим о настройке запросов и параметров подключения, конфигурации Autovacuum. А также обсудим необходимость разделения. «PostgreSQL База»  Редактор в MobileUp