# Буферный кеш и вытеснение _Буферный кеш и WAL · PostgreSQL Knowledge Base_ **TL;DR:** Буферный кеш - разделяемая память (shared_buffers), нарезанная на буферы по 8 КБ. Все бэкенды работают с одним кешем. Когда место кончается, буфер выселяется по приближённому алгоритму clock-sweep (счётчик usage_count), а не по честному LRU. ## Устройство Буферный кеш - область разделяемой памяти размером `shared_buffers`, нарезанная на слоты по 8 КБ (страница). PostgreSQL никогда не работает с данными на диске напрямую: страница сначала поднимается в буфер, дальше чтение и изменение идут в памяти. Все процессы видят один кеш - если страницу поднял один бэкенд, остальные найдут её там же. ## Clock-sweep вместо LRU Когда нужен новый буфер, а все заняты, кого-то выселяют. Честный LRU дорого поддерживать под конкуренцией, поэтому используется приближённый clock-sweep: - у каждого буфера есть счётчик `usage_count`, растущий при обращении; - «стрелка» ходит по буферам по кругу; - если `usage_count > 0` - уменьшает его и идёт дальше; - если `usage_count = 0` и буфер не «прибит» (pinned) - выселяет его. Часто используемые страницы переживают много кругов, одноразовые быстро вылетают. Грязный буфер перед выселением записывается на диск. ## Кто пишет грязные буферы - **bgwriter** - заранее, фоном, чтобы бэкендам было куда селить страницы; - **checkpointer** - все грязные буферы в контрольной точке (см. [checkpoint](/courses/postgres/kb/checkpoint.md)); - **сам бэкенд** - если нет свободных буферов; тормозит запрос, плохой признак. ## Заглянуть в кеш ```sql CREATE EXTENSION IF NOT EXISTS pg_buffercache; SELECT count(*), count(*) FILTER (WHERE isdirty) AS dirty FROM pg_buffercache WHERE relfilenode = pg_relation_filenode('flights'); ``` `pg_buffercache` показывает каждый буфер; `pg_buffercache_summary` (PG16) отдаёт дешёвый агрегат без построчного скана. Состояния обращения разбирает [buffer-states](/courses/postgres/kb/buffer-states.md), а кольцо для больших сканов - [buffer-ring](/courses/postgres/kb/buffer-ring.md). ## Команды ```sql SELECT * FROM pg_buffercache_summary(); ``` Сводка по кешу: занято, грязных, средний usage_count (PG16) ```sql SELECT count(*) FROM pg_buffercache WHERE relfilenode = pg_relation_filenode('flights'); ``` Сколько буферов занимает конкретная таблица ```sql SHOW shared_buffers; ``` Размер буферного кеша ## См. также - [Четыре состояния буфера](/courses/postgres/kb/buffer-states.md) - [Буферное кольцо для seq scan](/courses/postgres/kb/buffer-ring.md) - [Контрольные точки и восстановление](/courses/postgres/kb/checkpoint.md)