(java || kotlin) && devOps
356 subscribers
7 photos
1 video
7 files
354 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
PostgreSQL и кэш

Речь не про кэширование JPA, а про собственное кэширование БД.

1) на сервере есть 2 уровня кэширования: PostgreSQL buffer cache и Linux page cache. В отличие от Kafka, где он один.
А если использовать кэширование на уровне JPA, в итоге получается 4 уровня)

2) по умолчанию кэша выделяется мало, для PROD like его размер нужно увеличить.
Посмотреть сколько:
SHOW shared_buffers


Изменить:
ALTER SYSTEM SET shared_buffers TO <your_value>; -- при наличии прав


или через /etc/postgresql/../postgresql.conf
c рестартом сервера.

Универсальных рекомендаций по размеру быть не может, но можно начать с 1/4 ОЗУ.

3) размером Linux page cache напрямую управлять нельзя. Но его максимальный размер можно ограничить косвенно, через
sysctl vm.swappiness

Да, это процент использования swap файла, но как побочный эффект он ограничивает использование ОЗУ под page cache, и оставшееся пространство можно выделить PostgreSQL.

Зная эти два параметра можно рассчитать максимальное значение для кэша PostgreSQL:

shared_buffers ~= ОЗУ * vm.swappiness - резерв ОС - резерв PostgreSQL


4) со значением shared_buffers нужно быть осторожным, также как и с настройкой heap space в JVM. PostgreSQL ожидает, что вся эта память будет ему доступна.
Если ОЗУ закончится, а процесс будет все равно пытаться запрашивать память, придет злой OOM Killer и убьет его).

5) есть расширение pg_buffercache, предоставляющее одноименное view с информацией о страницах кэша PostgreSQL: к какой таблице относится, как используется.
Перед его использованием нужно само собой установить:
CREATE EXTENSION pg_buffercache;

перегрузить сервер и дать права:
GRANT pg_monitor TO xxx;


Использование:
SELECT count(*)
FROM pg_buffercache
WHERE relfilenode = pg_relation_filenode('table'::regclass);


6) при старте PostgreSQL все кэши пустые.
Интересно, что "SELECT *" не заполняет кэш на 100%, т.к. используется более хитрый механизм, когда для каждой выполняемой операции выделяется часть кэша.
А вот изменение данных, которое тоже идет через буфер, точно кэширует все изменяемые данные.

7) изменение данных - плохой способ заполнить кэш.
А часто прогреть кэш нужно, как минимум для справочных данных.
Да вообще говоря и для любых данных, т.к. если удастся поместить всю БД в кэш, то это ускорит работу с БД на пару порядков (ОЗУ vs диски).
Ну и если быть точным - ускорит серверную часть процесса, см. https://t.me/javaKotlinDevOps/487

И ... для прогрева кэша тоже есть расширение:

CREATE EXTENSION pg_prewarm;
ALTER SYSTEM SET shared_preload_libraries = 'pg_prewarm';

и рестарт.

Использование:
SELECT pg_prewarm('table');


8) PostgreSQL сам чистит кэш в фоновом режиме, а явно сбросить кэш можно только перезагрузкой сервера. Что-то мне это напоминает из мира Java)

#cache #postgresql #performance