Настройка параметров ядра Linux для оптимизации PostgreSQL

Original author: Ibrar Ahmed
  • Translation
Оптимальная производительность PostgreSQL зависит от правильно определенных параметров операционной системы. Плохо настроенные параметры ядра ОС могут привести к снижению производительности сервера базы данных. Поэтому обязательно, чтобы эти параметры были настроены в соответствии с сервером базы данных и его рабочей нагрузкой. В этом посте мы обсудим некоторые важные параметры ядра Linux, которые могут повлиять на производительность сервера базы данных и способы их настройки.

SHMMAX / SHMALL


SHMMAX — это параметр ядра, используемый для определения максимального размера одного сегмента разделяемой памяти (shared memory), который может выделить процесс Linux. До версии 9.2 PostgreSQL использовал System V (SysV), для которой требуется настройка SHMMAX. После 9.2 PostgreSQL переключился на разделяемую память POSIX. Так что теперь требуется меньше байтов разделяемой памяти System V.

До версии 9.3 SHMMAX был наиболее важным параметром ядра. Значение SHMMAX задается в байтах.

Аналогично, SHMALL — это еще один параметр ядра, используемый для определения
общесистемного объема страниц разделяемой памяти (shared memory). Чтобы просмотреть текущие значения SHMMAX, SHMALL или SHMMIN, используйте команду ipcs.

SHM* Details — Linux

$ ipcs -lm

------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 1073741824
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1

SHM* Details — MacOS X

$ ipcs -M
IPC status from  as of Thu Aug 16 22:20:35 PKT 2018
shminfo:
	shmmax: 16777216	(max shared memory segment size)
	shmmin:       1	(min shared memory segment size)
	shmmni:      32	(max number of shared memory identifiers)
	shmseg:       8	(max shared memory segments per process)
	shmall:    1024	(max amount of shared memory in pages)

PostgreSQL использует System V IPC для выделения разделяемой памяти. Этот параметр является одним из наиболее важных параметров ядра. Всякий раз, когда вы получаете следующие сообщения об ошибках, это означает, что у вас более старая версия PostgreSQL и у вас очень низкое значение SHMMAX. Ожидается, что пользователи будут корректировать и увеличивать значение в соответствии с разделяемой памятью, которую они собираются использовать.

Возможные ошибки неправильной конфигурации


Если SHMMAX настроен неправильно, вы можете получить ошибку при попытке инициализировать кластер PostgreSQL с помощью команды initdb.

initdb Failure
DETAIL: Failed system call was shmget(key=1, size=2072576, 03600).

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. 
You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 2072576 bytes),
reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.

The PostgreSQL documentation contains more information about shared memory configuration. child process exited with exit code 1


Аналогично, вы можете получить ошибку при запуске сервера PostgreSQL используя команду pg_ctl.

pg_ctl Failure
DETAIL: Failed system call was shmget(key=5432001, size=14385152, 03600).

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter.

You can either reduce the request size or reconfigure the kernel with larger SHMMAX.; To reduce the request size (currently 14385152 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.

The PostgreSQL documentation contains more information about shared memory configuration.


Понимание различий в определениях


Определение параметров SHMMAX/SHMALL немного отличается в Linux и MacOS X:

  • Linux: kernel.shmmax, kernel.shmall
  • MacOS X: kern.sysv.shmmax, kern.sysv.shmall

Команда sysctl может быть использована для временного изменения значения. Чтобы установить постоянные значения, добавьте запись в /etc/sysctl.conf. Подробности приведены ниже.

Изменение параметров ядра на MacOS X

# Get the value of SHMMAX
sudo sysctl kern.sysv.shmmax
kern.sysv.shmmax: 4096

# Get the value of SHMALL
sudo sysctl kern.sysv.shmall 
kern.sysv.shmall: 4096

# Set the value of SHMMAX
sudo sysctl -w kern.sysv.shmmax=16777216
kern.sysv.shmmax: 4096 -> 16777216

# Set the value of SHMALL 
sudo sysctl -w kern.sysv.shmall=16777216
kern.sysv.shmall: 4096 -> 16777216

Изменение параметров ядра на Linux

# Get the value of SHMMAX
sudo sysctl kernel.shmmax
kernel.shmmax: 4096

# Get the value of SHMALL
sudo sysctl kernel.shmall
kernel.shmall: 4096

# Set the value of SHMMAX
sudo sysctl -w kernel.shmmax=16777216
kernel.shmmax: 4096 -> 16777216

# Set the value of SHMALL 
sudo sysctl -w kernel.shmall=16777216
kernel.shmall: 4096 -> 16777216

Не забудьте: чтобы сделать изменения постоянными, добавьте эти значения в /etc/sysctl.conf

Большие страницы (Huge Pages)


В Linux по умолчанию используются страницы памяти 4 КБ, в BSD — Super Pages, а в Windows — Large Pages. Страница — это часть оперативной памяти, выделенная процессу. Процесс может иметь несколько страниц в зависимости от требований к памяти. Чем больше памяти требуется процессу, тем больше страниц ему выделено. ОС поддерживает таблицу выделения страниц для процессов. Чем меньше размер страницы, тем больше таблица, тем больше времени требуется для поиска страницы в этой таблице страниц. Поэтому большие страницы позволяют использовать большой объем памяти с уменьшенными накладными расходами; меньше просмотров страниц, меньше ошибок страниц, более быстрые операции чтения/записи через большие буферы. Как результат — улучшение производительности.

PostgreSQL поддерживает большие страницы только в Linux. По умолчанию Linux использует 4 КБ страниц памяти, поэтому в случаях, когда операций с памятью слишком много, необходимо устанавливать страницы большего размера. Наблюдается прирост производительности при использовании больших страниц размером 2 МБ и до 1 ГБ. Размер большой страницы может быть установлен во время загрузки. Вы можете легко проверить параметры большой страницы и их использование на вашем Linux-компьютере, используя команду cat /proc/meminfo | grep -i huge.

Получение информации о больших страницах (только на Linux)

Note: This is only for Linux, for other OS this operation is ignored$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

В этом примере, хотя размер большой страницы установлен в 2048 (2 МБ), общее количество больших страниц имеет значение 0. Это означает, что большие страницы отключены.

Скрипт определения количества больших страниц


Это простой скрипт возвращает необходимое количество больших страниц. Запустите скрипт на вашем сервере Linux, пока работает PostgreSQL. Убедитесь, что для переменной среды $PGDATA задан каталог данных PostgreSQL.

Получение цифры требуемых больших страниц

#!/bin/bash
pid=`head -1 $PGDATA/postmaster.pid`
echo "Pid:            $pid"
peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'`
echo "VmPeak:            $peak kB"
hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'`
echo "Hugepagesize:   $hps kB"
hp=$((peak/hps))
echo Set Huge Pages:     $hp

Вывод скрипта выглядит следующим образом:

Вывод скрипта

Pid:            12737
VmPeak:         180932 kB
Hugepagesize:   2048 kB
Set Huge Pages: 88

Рекомендуемое значение больших страниц — 88, поэтому вы должны установить значение 88.

Установка больших страниц

sysctl -w vm.nr_hugepages=88

Проверьте большие страницы сейчас, вы увидите, что большие страницы не используются (HugePages_Free = HugePages_Total).

Снова информация о больших страницах (только на Linux)

$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:      88
HugePages_Free:       88
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

Теперь задайте параметр huge_pages «on» в $PGDATA/postgresql.conf и перезапустите сервер.

И снова информация о больших страницах (только на Linux)

$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:      88
HugePages_Free:       81
HugePages_Rsvd:       64
HugePages_Surp:        0
Hugepagesize:       2048 kB

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

Некоторые операции с базой данных для утилизации больших страниц

postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000

Давайте посмотрим, используем ли мы сейчас больше больших страниц, чем раньше.

Еще раз информация о больших страницах (только на Linux)

$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:      88
HugePages_Free:       18
HugePages_Rsvd:        1
HugePages_Surp:        0
Hugepagesize:       2048 kB

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

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

vm.swappiness


vm.swappiness — это еще один параметр ядра, который может влиять на производительность базы данных. Этот параметр используется для управления поведением подкачки (swappiness) (подкачки страниц в память и из нее) в Linux. Значение варьируется от 0 до 100. Он определяет, сколько памяти будет выгружено или выгружено. Ноль означает отключение обмена, а 100 означает агрессивный обмен.

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

Установка значения 0 в более новых ядрах может привести к тому, что OOM Killer (процесс очистки памяти в Linux) убьет процесс. Таким образом, можно безопасно установить значение 1, если хотите минимизировать подкачку. Значение по умолчанию в Linux — 60. Более высокое значение заставляет MMU (блок управления памятью) использовать больше пространства подкачки, чем ОЗУ, тогда как более низкое значение сохраняет больше данных/кода в памяти.

Меньшее значение — хорошая ставка на улучшение производительности в PostgreSQL.

vm.overcommit_memory / vm.overcommit_ratio


Приложения получают память и освобождают ее, когда она больше не нужна. Но в некоторых случаях приложение получает слишком много памяти и не освобождает ее. Это может вызвать OOM killer. Вот возможные значения параметра vm.overcommit_memory с описанием для каждого:

  1. Эвристический overcommit (по умолчанию); основанная на ядре эвристика
  2. Разрешить overcommit в любом случае
  3. Не переусердствуйте, не превышайте overcommit коэффициент.

Ссылка: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting

vm.overcommit_ratio — процент оперативной памяти, доступной для чрезмерной загрузки. Значение 50% в системе с 2 ГБ ОЗУ может выделять до 3 ГБ ОЗУ.

Значение 2 для vm.overcommit_memory обеспечивает лучшую производительность для PostgreSQL. Это значение максимизирует использование оперативной памяти серверным процессом без какого-либо значительного риска быть убитым процессом OOM killer. Приложение сможет перезагружаться, но только в пределах перерасхода, что снижает риск того, что OOM killer убьет процесс. Следовательно, значение 2 дает лучшую производительность, чем значение по умолчанию 0. Тем не менее, надежность может быть улучшена за счет того, что память за пределами допустимого диапазона не будет перегружена. Это исключает риск того, что процесс будет убит OOM-killer.

В системах без подкачки может возникнуть проблема с vm.overcommit_memory равным 2.

https://www.postgresql.org/docs/current/static/kernel-resources.html#LINUX-MEMORY-OVERCOMMIT

vm.dirty_background_ratio / vm.dirty_background_bytes


vm.dirty_background_ratio — это процент памяти, заполненной грязными страницами, которые необходимо записать на диск. Сброс на диск производится в фоновом режиме. Значение этого параметра колеблется от 0 до 100; однако значение ниже 5 может быть неэффективным, и некоторые ядра его не поддерживают. 10 — значение по умолчанию в большинстве систем Linux. Вы можете повысить производительность для операций с интенсивной записью с меньшим коэффициентом, который будет означать, что Linux будет сбрасывать грязные страницы в фоновом режиме.

Вам нужно установить значение vm.dirty_background_bytes в зависимости от скорости вашего диска.

Для этих двух параметров нет «хороших» значений, так как оба зависят от аппаратного обеспечения. Однако установка vm.dirty_background_ratio в значение 5 и vm.dirty_background_bytes в 25% от скорости диска, повышает производительность до ~ 25% в большинстве случаев.

vm.dirty_ratio / dirty_bytes


Это то же самое, что vm.dirty_background_ratio / dirty_background_bytes, за исключением того, что сброс выполняется в рабочем сеансе, блокируя приложение. Поэтому vm.dirty_ratio должно быть выше, чем vm.dirty_background_ratio. Это гарантирует, что фоновые процессы будут запускаться раньше, чтобы избежать максимально возможной блокировки приложения. Вы можете настроить разницу между этими двумя соотношениями в зависимости от загрузки дискового ввода-вывода.

Итог


Вы можете настроить другие параметры для увеличения производительности, но улучшения будут минимальными и выгоды особой не получите. Мы должны помнить, что не все параметры относятся ко всем типам приложений. Некоторые приложения работают лучше, когда мы настраиваем некоторые параметры, а некоторые — нет. Вы должны найти правильный баланс между конфигурациями этих параметров для ожидаемой рабочей нагрузки и типа приложения, а также при настройке необходимо учитывать поведение ОС. Настроить параметры ядра не так просто, как настроить параметры базы данных: здесь сложнее давать свои рекомендации.
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 26

    +7
    До версии 9.3 SHMMAX был наиболее важным параметром ядра.

    Вот эту мысль надо выделить ещё раз и отдельно. Потому что на 9.3+ этот параметр из важного перекочевал в бесполезный. Не влияет касательно базы ни на что. Как и shmall

    А если у вас стоит что-то настолько древнее — то вам необходимо не ядро крутить, а обновлять базу. Уже 9.4.х ветка скоро EOL будет. То есть не будет ни багфиксов, ни исправлений безопасности.

    PostgreSQL поддерживает большие страницы только в Linux.

    Начиная с 11 — и windows. Кому-то понадобилось и сделали.

    Размер большой страницы может быть установлен во время загрузки.

    2мб страницы vm.nr_hugepages под linux спокойно меняются на лету. Может понадобиться сбросить файловый кэш, изменение числа страниц не вытесняет память кэша.
    гигабайтные страницы — надо проверять поддержку со стороны CPU, и эти да, могут выделяться только при старте ОС.
    Мы на рабочем проекте замеряли — разницу между 2мб и 1гб страницами не нашли.
    А вот между 2мб и 4кб страницами при объёмах shared_buffers от 32гб — must have.

    Сразу момент: shared memory в postgresql это не только shared_buffers. shared_buffers — это только буфер блоков, даже без учёта управляющих этих блоком структур. Суммарно объём shared memory выделяется где-то на 3% больше чем заявлен shared_buffers.

    Теперь задайте параметр huge_pages «on»

    По-умолчанию он try. То есть для использования huge pages достаточно только рестартовать базу.
    try означает, что база сначала попробует запросить huge pages, если не удастся — попросит сегмент обычной памяти.
    на on — при неудаче с huge pages выключится с ошибкой.

    Может быть плохой идеей выдавать huge pages ровно под обрез объёма выделяемой базой памяти. Так поднимете тот же max_connections — и база при рестарте не запустится.

    vm.dirty_*ratio опасны тем, что вот у вас средняя железка с 256гб памяти. И всего-то 5% от них — это уже до 12 гигабайт данных, которые вдруг начинают лететь на диск одним махом потому что база запросила fsync. И всё, диски перегружены и тормозят. Даже на хороших SSD записать 12 гигабайт random write — это не микросекунды вопрос. Они только по интерфейсу даже pci-e nvme дисков несколько секунд пропихиваться будут.
    А если у вас не хорошие SSD ориентированные на пишущую нагрузку (а таких подавляющее большинство) — то сразу начинаются фокусы вроде ой, простой insert одной строки работает больше секунды. Потому что диск стал резко перегружен и не отвечает на fsync записи в WAL.
    Поэтому только *_bytes и при том весьма агрессивные. Что-то вроде сотни мегабайт dirty_bytes и гигабайт-два dirty_background_bytes.
      +3

      Тот случай когда комментарий на порядок полезней статьи.

        0
        простой insert одной строки работает больше секунды. Потому что диск стал резко перегружен и не отвечает на fsync записи в WAL

        А разве оно не будет ждать только, если включен synchronous_commit?
        Мы на многих базах его выключаем по этой причине, так как во многих процессах не так страшно, что транзакция как бы прошла, а на самом деле нет (fsync понятно, что самоубийство отключать).
          +1
          Дефолтно-то синхронный коммит включен. И крутят его только если знают о такой настройке. А так — да, ждать запись не будет (хотя может и будет в граничном случае когда пытаемся писать больше чем успеваем делать асинхронный fsync WAL, гарантируется же потеря только до 3*wal_writer_delay. Надо читать исходник). И я полностью согласен что для многих баз synchronous_commit=on — не очень нужное насилие над железом. Тем более эту настройку можно хоть на отдельную транзакцию переключать, это простой PGC_USERSET. При капитальном крахе ОС потерять до 3*wal_writer_delay или wal_writer_flush_after объём записи критично не так уж повсеместно.

          Просто пример показательный из практики.
            +1
            Дефолтно-то синхронный коммит включен

            Да, поэтому мы во всех настройках, как правило, его выключаем. При этом почему-то во многих примерах в интернете, его не отключают.
            Кстати, я там в конце статьи написал комментарий. Вы, как опытный специалист, может сталкивались с этим? Если да, то какие варианты решения проблема могут быть.
        0
        на on — при неудаче с huge pages выключится с ошибкой.

        Так и есть. Postgre просто не рестартанет

        Вообще, если сравнивать производительность shared_buffers vs huge_pages, то с большим размером shared_buffers слоник работает быстрее, в некоторых местах прямо ощутимее. Так что на мой взгляд лучше выделить большой объем памяти shared_buffers, чем активировать huge_pages в ОС, установив маленький размер shared_buffers
          +1
          эээ… Вы о чём это? Как и зачем сравнивать несравнимое?

          shared_buffers крутить необходимо само собой разумеется. Дефолтная настройка не для работы, а чтобы запуститься на любой кофеварке.
          А если вы выделите много huge pages, которые не будете использовать — да лучше выньте из сервера планку памяти и продайте её, раз уж всё равно не используете. Выделенные huge pages не используются под page cache и в нормальной работе базы. Только под shared memory. Если вы на 128гб всего памяти выделите 32гб в huge pages, а shared_buffers поставите в 8 гб — то остальные 24гб вы тупо выбросите. Они не будут использоваться ни для чего.
            0

            Если накатываете реплику, делая потоковую репликацию, сделайте шаред на реплики очень мелким вначале, это ускорит поднятие в разы…

              0
              Так же справедливо для pitr. Есть места, где делается перебор всего shared_buffers.
              0
              Ну вот есть дилемма — использовать память для shared buffer или отдать ее часть под huge pages и где получить максимальную произоводительность. Проэкспериментировал у себя со стандартными настройками huge pages = 2 МБ, и пришел к выводу, что у меня без huge pages работает слоник быстрее
                +1
                где дилемма? Нет никакой дилеммы.
                Выделяете huge pages, затем запускаете базу — база размещает shared_buffers используя huge pages. Здесь нет выбора или huge pages или shared_buffers. Вы выделяете huge pages и там размещается shared memory. Объём занятой памяти под буфер от этого не меняется. Но зато радикально сокращается оверхед на управление этой памятью ядром ОС.
                  0
                  Может я что-то не понимаю из того, что вы написали. Но. В настройках postgresql.conf если я оставляю значение, которое было до включения huge_pages, например 4GB, то постгре не стартует, а сообщает, что не хватает памяти. Пока не уменьшу, к примеру, значение shared_buffers до 128MB, постгре не стартует
                    0
                    вы huge pages выделили достаточно чтобы туда shared memory влез?
                    shared memory в postgresql это не только shared_buffers. shared_buffers — это только буфер блоков, даже без учёта управляющих этих блоком структур. Суммарно объём shared memory выделяется где-то на 3% больше чем заявлен shared_buffers.


                    вы проверили, что huge pages действительно выделились после sysctl -p?
                    2мб страницы vm.nr_hugepages под linux спокойно меняются на лету. Может понадобиться сбросить файловый кэш, изменение числа страниц не вытесняет память кэша.


                    Ну и на скромных 4гб shared_buffers эффекта заметного не будет.
                      0
                      вы huge pages выделили достаточно чтобы туда shared memory влез?

                      Скорее всего нет. Нужно будет с этим поэксперементировать. Спасибо
                      вы проверили, что huge pages действительно выделились после sysctl -p?

                      Точно, проверил через значение HugePages_Rsvd
            0
            Есть еще один относительно важный параметр, с которым по крайней мере мы сталкивались регулярно: min_free_kbytes. Он проявлялся только на больших объемах оперативной памяти.
            По умолчанию, там стоит совсем маленькое значение (что-то около 128МБ). В таком случае ОС использует всю свободную память под кэши диска. И такое ощущение, что у ОС в определенные моменты начинается дикая фрагментация памяти, и она начинает очень долго выделять относительно крупные блоки памяти. В dstat это выглядит как внезапно возникший дикий sys. Если профайлить PostgreSQL, то он в этот момент висит в каком-то системном вызове (не помню каком), связанным именно с выделением памяти. Мы несколько раз на это нарывались и поднятие min_free_kbytes хотя бы до 1-2ГБ решало проблему.
            Кроме того, vm.swappiness выставленный 1 по непонятной причине очень часто не помогает. И Linux вместо того, чтобы освобождать кэши диска, начинает зачем-то загонять память в своп. Причем часто под нее почему-то попадают какие-то важные участки памяти postmaster'а, что весь PostgreSQL начинает подвисать. Решалось это уменьшением shared_buffers, work_mem и temp_buffers (просто за счет того, что потреблялось меньше памяти).
            Кто-нибудь еще с этим сталкивался с этими 2мя проблемами?
              0

              Я больше скажу, мне min_free_kbytes даже на raspberrypi с 512мб памяти крутить пришлось =) иначе под нагрузкой сеть временно отваливалась с руганью в dmesg что нет памяти под сетевой буфер. На больших машинках да, где-то гигабайт выделяем всегда под эту настройку.


              А вот по свапу не знаю, свап обязательно делаем, swapinnes ставим в 1, проблем отсюда не припоминаю.

                0
                Про min_free_kbytes неплохо написано вот в этой статье. Собственно там, я и нашел решение. А вот со swappiness их способом, я не смог, к сожалению, побороться.
                0
                По первой проблеме у вас может быть включен Transparet Huge Page?
                  0
                  Пробовал в обоих положениях — не помогало никак. А вообще обычно выключен.
                  0
                  Я сталкивался с PostgreSQL с большими БД, фрагментацию памяти можно увидеть несколькими способами:
                  1. Самый простой это htop с показом тредов ядра, всегда в топе будет висеть kswapd{0,1} и большой systime
                  2. perf top, isolate_freepages_block, будет в топе висеть.
                  Вот тут хорошо эта ситуация описана: habr.com/ru/company/odnoklassniki/blog/266005
                  vm.swappiness это софт порог, если памяти не хватает, например в следствии фрагментации, то все равно будет swap. Вариант крутить min_free_kbytes и отключить swap вообще, как бы если БД туда пошла это все равно уже могила, вывод не правильно отсайзили сервер.
                  Для PostgreSQL лучше использовать Huge Pages, так как большие страницы не подвержены фрагментации, поэтому под нужды PostgreSQL (при правильном сайзинге) всегда будет память.
                  И да тут в статье не написано, но желательно HugePages запереть под процесс через vm.hugetlb_shm_group = GID (PostgreSQL) и будет счастье. И отрубить Transparent Huge Pages это зло
                  (https://habr.com/ru/company/tinkoff/blog/446342/). Для БД например IBM, RedHat рекомендует отключать.
                  А вот что может еще немного ускорить БД: увеличение kernel.sched_migration_cost_ns = 500000 -> kernel.sched_migration_cost_ns = 5000000 (на порядок)
                  Хорошо про это рассказывал Илья Космодемьянский из Data Egret на HiLoad. Если вкратце, то время работы процесса на 1 ядре будет увеличено до миграции на другое или сна, тем самым вероятность выполнения 1 транзакции за проход увеличивается.
                  И следите за NUMA зонами, пример, 1 физ сервер с 2 сокетами. Память делиться на 2 NUMA зоны. Одна ближе к 1 сокету, 2-ая зона ко второму. Если вы аллоцируете память под shared_buffers больше чем 1 зона NUMA, то при заполнении 1 зоны память из второй не будет использоваться, а процессы пойдут в swap. Поэтому если ожидается такой кейс, необходимо использовать NUMA interleaving (править стартовые скрипты, добавляя numactl --interleave=all перед стартом процесса PostgreSQL)
                    0
                    По поводу NUMA совершенно верно сказано. Но отдельно хочу заострить внимание — речь всё-таки не о сокетах CPU, а о NUMA нодах. Например, они в листинге lscpu видны. Фокус в том, что они не всегда очевидно сопоставляются с числом сокетов. Так, к примеру, AMD EPYC 7551P — это один CPU, один сокет, но распознаётся как 4 раздельные NUMA.
                    И особое веселье тут начинается, когда приличный объём данных скапливается в одной NUMA ноде, а процессы из других нод начинают активно ходить в чужую относительно них память. Начинают нагружать этот один контроллер памяти, шины между ядрами, а у postgresql многие локи и межпроцессное взаимодействие именно через shared_memory работает и потому чувствительно к latency памяти. В общем, вдруг получается большая разница производительности смотря на ядро CPU какой группы NUMA операционная система отправила процесс базы.
                    PostgreSQL сам к сожалению не умеет работать с NUMA от слова вообще. И самое лучше что тут можно сделать — перевести систему в NUMA interleave режим. Тогда это будет да, неэффективно с точки зрения сухой теории, мы не используем преимущества локальных NUMA нод, а размазываем память ровным слоем по всем. Но у нас равномерно утилизированы контроллеры памяти и в результате работа запросов более равномерная независимо от того, на каком ядре CPU (и какого CPU в многосокетных конфигах) выполняется.
                    Удобнее всего — выключить вообще глобально в bios или параметром numa=off в cmdline ядра. Патчить инитскрипты всё-таки порядком неудобно, эти правки перетираются с обновлениями и про них легко забыть.

                    Ещё рядом с kernel.sched_migration_cost_ns Илья по идее должен был говорить про kernel.sched_autogroup_enabled=0
                    Чего ещё не упоминали в комментариях здесь?
                    vm.zone_reclaim_mode = 0
                    kernel.numa_balancing=0
                    vm.hugepages_treat_as_movable = 0

                    Ну и рядом с настройками ядра для комплекта — указание на powersave режимы CPU. CPU нагрузку из коротких быстрых запросов может не считать поводом выходить из powersave режима и может не поднимать частоту даже до своей номинальной. Переключение в performance может сильно улучшить жизнь (см /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor или какие гайки поверх этого приняты в вашем дистрибьютиве, обычно какой-то сервис при загрузке выставляет режим)
                    Ну плюс выбрать io scheduler под свою систему хранения.

                    PS: в общем, если кто надумает собрать из комментариев здесь ещё одну статью по настройкам ядра под postgresql — упомяните Data Egret в источниках, я ведь тоже оттуда ;-)
                      0
                      Спасибо. Очень полезно.
                      Удобно, наверное сделать какой-то образ системы под базу с уже установленными всеми настройками как операционки, так и PostgreSQL. Понятно, что они могут отличаться от железа, но все равно — дефолтные настройки в ОС и PostgreSQL явно не адаптированы ни под что и их придется менять в любом случае.
                        0
                        Вообще на системе только под базу не так уж и много мест надо крутить для среднего по больнице случая. Немного sysctl, десятка два настроек postgresql, pgbouncer, cpu powersave, чуток кроновых скриптов. Образ системы городить тут как-то избыточно. Удобнее ansible и подобные или даже просто задокументировать во внутренней вики.
                          0
                          Для быстрых хранилок, неплохо включить: blk-mq, плюс если 4-е ядро и доступно mq-deadline, например
                            0
                            Угу, я поленился про шедулеры расписывать, ограничившись
                            Ну плюс выбрать io scheduler под свою систему хранения.


                            С 4.19 ядер blk_mq семейство активно дефолтно, а с 5.0 уже старые планировщики удалили.
                  0
                  Значение варьируется от 0 до 100. Он определяет, сколько памяти будет выгружено или выгружено. Ноль означает отключение обмена, а 100 означает агрессивный обмен.

                  В интернете миф про процентное соотношение вытеснения в подкачку (vm.swappiness) ходит полезный, но не верный.
                  Увы в исходниках ядра указано, что параметр имеет значения от 0 до 100, но по факту он от 0 до 200, где 200 это 100%, а 0 это >0%.
                  Так же в исходном коде ядра, я не обнаружил проверку для диапазона этого параметра.

                  Что касается значения 0, то он не отключает обмен, вот ссылка на патч где указано, что до применения этого патча 1 и 0 значения были паритетными, а сейчас поведение будет не тем которое вы ожидаете (не отключит использование подкачки). Поведение достаточно специфичное, я не изучал всю логику, т.к. в работе лучше использовать инструменты, которые упрощают выполнение задач, а не усложняют для бизнеса. Я не обладаю достаточным временем для того чтобы проанализировать в каких ядрах этот патч применён, но уверен что для подавляющего большинства ваших хостов он применён.

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

                  Ссылки по теме:

                  habr.com/ru/company/flant/blog/348324
                  git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/vmscan.c#n2357

                  Only users with full accounts can post comments. Log in, please.