Оптимизация дисковой подсистемы
В данной статье на XDR описаны общие рекомендации, которые также применимы к функциональности KEDR. Нас интересует именно требования к дискам и хранилищам.
Перед дальнейшими изменениями можете выполнить команду на сервере СУБД и записать результаты:
fio --name=test --directory=/var/lib/postgresql/<ваша_версия>/main --rw=randrw --bs=8k --size=1G --iodepth=16 --ioengine=libaio --direct=1 --fsync=1 --runtime=60
Для начала выполним быструю проверку типа диска:
lsblk -d -o name,rota,TYPE,MODEL,SIZE
Ожидаемые выводы и их интерпритация:
#Пример 1: SSD
NAME ROTA TYPE MODEL SIZE
sda 0 disk Samsung_SSD_860 500G # ROTA=0 (SSD)
#Пример 2: HDD
NAME ROTA TYPE MODEL SIZE
sda 1 disk WDC_WD10EZEX 1T # ROTA=1 (HDD)
#Пример 3: Виртуальный диск (VMware)
NAME ROTA TYPE MODEL SIZE
sda 0 disk Virtual_disk 100G # ROTA=0 (считаем как SSD)
#Пример 4: NVMe
NAME ROTA TYPE MODEL SIZE
nvme0n1 0 disk INTEL_SSD 500G # NVMe (всегда SSD)
Далее настроим планировщие I/O:
Создадим udev правило и отредактируем его:
nano /etc/udev/rules.d/60-scheduler.rules
Для SSD (ROTA=0) вставим следующие значения:
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/nr_requests}="1024"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/max_sectors_kb}="2048"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/read_ahead_kb}="128"
Для HDD (ROTA=1):
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/nr_requests}="256"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/max_sectors_kb}="512"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/read_ahead_kb}="256"
Для NVMe (ROTA=0):
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="none"
ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/nr_requests}="1024"
И применим правила:
udevadm control --reload-rules
udevadm trigger --name-match=sda
Далее настроим параметры ядра (sysctl):
Создадим файл настроек и отредактируем его:
nano /etc/sysctl.d/99-database-tuning.conf
Для SSD / NVMe / Виртуальных дисков (ROTA=0):
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
fs.aio-max-nr = 2097152
vm.swappiness = 1
vm.vfs_cache_pressure = 50
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
Для HDD (ROTA=1):
vm.dirty_ratio = 30
vm.dirty_background_ratio = 10
vm.dirty_expire_centisecs = 6000
vm.dirty_writeback_centisecs = 3000
fs.aio-max-nr = 2097152
vm.swappiness = 1
vm.vfs_cache_pressure = 50
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
И применем настройки:
sysctl -p /etc/sysctl.d/99-database-tuning.conf
Далее настроим опции файловой системы:
Отредактируем fstab (предварительно сделайте резервную копию):
nano /etc/fstab
Найдём строку, как пример для ext4:
UUID=3fe51788-bb69-467d-89a9-a146c1df7fdd / ext4 defaults 1 1
Заменим на:
UUID=3fe51788-bb69-467d-89a9-a146c1df7fdd / ext4 rw,noatime,nodiratime,data=ordered,errors=remount-ro 1 1
Для xfs заменим на: noatime,nodiratime,logbufs=8,logbsize=256k
Далее перемонтируем корневую систему:
mount -o remount /
или перезагрузим систему.
Также рекомендую обновить systemd после изменения /etc/fstab:
systemctl daemon-reload
Далее настроим TRIM (только для SSD):
# Включить fstrim.timer:
systemctl enable --now fstrim.timer
# Проверить статус:
systemctl status fstrim.timer
Далее перепроверим конфигуарцию postgresql.conf:
nano /etc/postgresql/<ВЕРСИЯ>/main/postgresql.conf
# Переопределите следующие параметры:
listen_addresses = '*'
port = 5432
max_connections = 512
shared_buffers = 8GB # 25% от ОЗУ, минимум 3 ГБ
effective_cache_size = 24GB # 75% от ОЗУ
temp_buffers = 24MB
work_mem = 64MB
maintenance_work_mem = 1GB
max_stack_depth = 7MB # Для Linux: ulimit -s минус 1 МБ
effective_io_concurrency = 200 # 200 для SSD или 2 для HDD
max_parallel_workers_per_gather = 0
wal_buffers = 64MB
max_wal_size = 4GB
min_wal_size = 1GB
random_page_cost = 1.1 # 1.1 для SSD или 4.0 для HDD
log_hostname = 1
standard_conforming_strings = on # Обязательно должно быть 'on'
Повторно можете выполнить команду fio и сравнить с первоначальными результатами. Должны увидеть рост пропускной способности, уменьшение задержек, увеличение числа операций в единицу времени.