
Часто при замедлении работы базы данных первым решением кажется увеличение вычислительных ресурсов: больше ядер, памяти, быстрые диски. Однако существует и другой, более экономичный путь — заглянуть глубже, на уровень операционной системы, управляющей этими ресурсами.
Данная статья — это практический разбор реального кейса, где скрупулёзная настройка параметров подсистемы ввода-вывода, кэширования и планировщика задач Linux позволила поднять производительность PostgreSQL на впечатляющие 65%. Без замены железа, без увеличения лицензий, только за счёт грамотной оптимизации «фундамента», на котором работает СУБД.
Задача
Оценить качественное и количественное влияние изменения параметров операционной системы на производительность СУБД PostgreSQL.
Тестовая среда, инструменты и конфигурация СУБД:
СУБД: PostgreSQL 17
Тестовая база данных: pgbench (10GB, простая структура)
Условия тестирования: параллельная нагрузка от 5 до 22 сессий по каждому тестовому сценарию.
Тестовый сценарий-1 (SELECT): вес = 0.7
CREATE OR REPLACE FUNCTION scenario1() RETURNS integer AS $$ DECLARE test_rec record ; min_i bigint ; max_i bigint ; current_aid bigint ; current_tid bigint ; current_bid bigint ; current_delta bigint ; counter bigint; BEGIN --------------------------------------------------- --СЦЕНАРИЙ 1 - SELECT ONLY SELECT MAX(aid) INTO max_i FROM pgbench_accounts ; SELECT MIN(aid) INTO min_i FROM pgbench_accounts ; current_aid = floor(random() * (max_i - min_i + 1)) + min_i ; select br.bbalance into test_rec from pgbench_branches br join pgbench_accounts acc on (br.bid = acc.bid ) where acc.aid = current_aid ; --СЦЕНАРИЙ 1 - SELECT ONLY --------------------------------------------------- return 0 ; END $$ LANGUAGE plpgsql;
Тестовый сценарий-2 (UPDATE): вес = 0.2
CREATE OR REPLACE FUNCTION scenario2() RETURNS integer AS $$ DECLARE test_rec record ; min_i bigint ; max_i bigint ; current_aid bigint ; current_tid bigint ; current_bid bigint ; current_delta bigint ; counter bigint; BEGIN --------------------------------------------------- --СЦЕНАРИЙ 2 - SELECT + UPDATE --1)UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid; --2)SELECT abalance FROM pgbench_accounts WHERE aid = :aid; --3)UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid; --4) UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid; current_delta = (ROUND( random ())::bigint)*10 + 1 ; SELECT MIN(aid) INTO min_i FROM pgbench_accounts ; SELECT MAX(aid) INTO max_i FROM pgbench_accounts ; current_aid = floor(random() * (max_i - min_i + 1)) + min_i ; --1) UPDATE pgbench_accounts SET abalance = abalance + current_delta WHERE aid = current_aid ; --1) --2) SELECT abalance INTO test_rec FROM pgbench_accounts WHERE aid = current_aid ; --2) SELECT MIN(tid) INTO min_i FROM pgbench_tellers ; SELECT MAX(tid) INTO max_i FROM pgbench_tellers ; current_tid = floor(random() * (max_i - min_i + 1)) + min_i ; --3) UPDATE pgbench_tellers SET tbalance = tbalance + current_delta WHERE tid = current_tid ; --3) SELECT MIN(bid) INTO min_i FROM pgbench_branches ; SELECT MAX(bid) INTO max_i FROM pgbench_branches ; current_bid = floor(random() * (max_i - min_i + 1)) + min_i ; --4) UPDATE pgbench_branches SET bbalance = bbalance + current_delta WHERE bid = current_bid ; --4) -- СЦЕНАРИЙ 2 - OLTP return 0 ; END $$ LANGUAGE plpgsql;
Тестовый сценарий-3 (INSERT): вес = 0.1
CREATE OR REPLACE FUNCTION scenario3() RETURNS integer AS $$ DECLARE test_rec record ; min_i bigint ; max_i bigint ; current_aid bigint ; current_tid bigint ; current_bid bigint ; current_delta bigint ; counter bigint; BEGIN --------------------------------------------------- --СЦЕНАРИЙ 3 - INSERT ONLY SELECT MIN(aid) INTO min_i FROM pgbench_accounts ; SELECT MAX(aid) INTO max_i FROM pgbench_accounts ; current_aid = floor(random() * (max_i - min_i + 1)) + min_i ; SELECT MIN(tid) INTO min_i FROM pgbench_tellers ; SELECT MAX(tid) INTO max_i FROM pgbench_tellers ; current_tid = floor(random() * (max_i - min_i + 1)) + min_i ; SELECT MIN(bid) INTO min_i FROM pgbench_branches ; SELECT MAX(bid) INTO max_i FROM pgbench_branches ; current_bid = floor(random() * (max_i - min_i + 1)) + min_i ; SELECT random() * 1000.0 INTO current_delta; FOR counter IN 1..1000 LOOP INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES ( current_tid , current_bid , current_aid , current_delta , CURRENT_TIMESTAMP ); END LOOP; --ССЦЕНАРИЙ 3 - INSERT ONLY --------------------------------------------------- return 0 ; END $$ LANGUAGE plpgsql;
Базовые значения параметров IO
Общие параметры производительности:
vm.dirty_ratio = 30
vm.dirty_background_ratio = 10
Параметры IO-планировщика:
[none] mq-deadline kyber bfq
Настройки кэширования и буферизации:
vm.vfs_cache_pressure = 100
Параметры файловой системы:
/dev/mapper/vg_data-LG_data on /data type ext4 (rw,relatime)
Размер буферов для операций с блочными устройствами
read_ahead_kb=4096
Рекомендации по изменению параметров ОС.
Эксперимент-2: Общие параметры производительности
vm.dirty_ratio=10
vm.dirty_background_ratio=5
Эксперимент-3: Параметры IO-планировщика
[mq-deadline] kyber bfq none
Эксперимент-5: Настройки кэширования и буферизации
vm.vfs_cache_pressure=50
Эксперимент-7: Оптимизация параметров файловой системы
/dev/mapper/vg_data-LG_data on /data type ext4 (rw,noatime,nodiratime)
Эксперимент-8: Изменение размера буферов для операций с блочными устройствами
echo 256 > /sys/block/vdd/queue/read_ahead_kb
Итоговый результат

В результате оптимизации параметров подсистемы ввода-вывода операционной системы производительность СУБД PostgreSQL повысилась в среднем на 65% по сравнению с базовой конфигурацией.
Показатели производительности , ожиданий СУБД и метрик производительности IO в ходе экспериментов

Операционная скорость

Ожидания СУБД

IOPS

Пропускная способность (MB/s)

Длина очереди (aqu_sz)

Ожидание по чтению

Ожидание по записи

Итоговый вывод
Систематическая оптимизация параметров подсистемы IO — таких как настройки кэширования, планировщика операций ввода-вывода и параметров файловой системы — позволила достичь значительного повышения производительности PostgreSQL.
Суммарный эффект от внесённых изменений выразился в среднем увеличении операционной скорости на 65,09% по сравнению с базовой конфигурацией. Наиболее существенный вклад внесли корректировки размера буферов предварительного чтения (read_ahead_kb) и отключение избыточного обновления временных меток файлов (noatime, nodiratime).
Результаты подтверждают - целенаправленная настройка окружения ОС является критически важным этапом развёртывания высоконагруженных СУБД.
