Архитектура
Очистка
16
Авторские права
© Postgres Professional, 2017–2024
Авторы: Егор Рогов, Павел Лузанов, Илья Баштанов, Алексей Береснев
Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
Использование материалов курса
Некоммерческое использование материалов курса (презентации,
демонстрации) разрешается без ограничений. Коммерческое
использование возможно только с письменного разрешения компании
Postgres Professional. Запрещается внесение изменений в материалы
курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу:
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за
любые повреждения и убытки, включая потерю дохода, нанесенные
прямым или непрямым, специальным или случайным использованием
материалов курса. Компания Postgres Professional не предоставляет
каких-либо гарантий на материалы курса. Материалы курса
предоставляются на основе принципа «как есть» и компания Postgres
Professional не обязана предоставлять сопровождение, поддержку,
обновления, расширения и изменения.
2
Темы
Задачи, требующие периодического выполнения
Автоочистка
Очистка и анализ вручную
Разрастание таблиц и индексов
Полная очистка и перестроение индексов
3
Периодические задачи
Очистка страниц от исторических данных,
которые образуются из-за многоверсионности
из таблиц вычищаются мертвые версии строк
из индексов вычищаются записи, ссылающиеся на мертвые версии
Механизм многоверсионности позволяет эффективно реализовать
изоляцию на основе снимков, но в результате в табличных страницах
накапливаются старые версии строк, а в страницах индексов — ссылки
на эти версии. Какое-то время исторические версии нужны, чтобы
транзакции могли работать со своими снимками данных. Но со
временем не остается ни одного снимка данных, которому требовалась
бы старая версия строки; такая версия называется «мертвой».
Процедура очистки вычищает мертвые версии строк из табличных
страниц и ненужные индексные записи, которые ссылались на такие
версии.
Если своевременно не вычищать исторические данные, таблицы и
индексы будут неконтролируемо разрастаться и поиск в них актуальных
версий строк будет замедляться.
4
Периодические задачи
Обновление карты видимости
отмечает страницы, на которых все версии строк видны во всех снимках
используется для оптимизации работы процесса очистки
и ускорения индексного доступа
существует только для таблиц
Кроме этой главной задачи, процедура очистки берет на себя и другие
задачи по поддержанию работоспособности экземпляра. Очистка
обновляет карту видимости и карту свободного пространства. Это
служебная информация, которая хранится вместе с основными
данными.
В карте видимости отмечены страницы, которые содержат только
актуальные версии строк, видимые во всех снимках данных. Иными
словами, это страницы, которые давно не изменялись и успели
полностью очиститься от неактуальных версий.
Карта видимости применяется:
Для оптимизации очистки.
В отмеченные страницы очистке не надо заглядывать — в них не
может быть мертвых версий.
Для ускорения доступа только по индексу.
Информация о версионности хранится только для таблиц, но не для
индексов (поэтому у индексов не бывает карты видимости). Получив
из индекса ссылку на версию строки, нужно прочитать табличную
страницу, чтобы проверить ее видимость. Но если в самом индексе
уже есть все нужные столбцы, и при этом страница отмечена в карте
видимости, то обращения к таблице можно избежать.
Если не обновлять карту видимости, индексный доступ будет работать
менее эффективно. Более подробно об этом рассказывается в курсе
QPT «Оптимизация запросов».
5
Периодические задачи
Обновление карты свободного пространства
отмечает свободное пространство в страницах после очистки
используется при вставке новых версий строк
существует и для таблиц, и для индексов
В карте свободного пространства отмечен объем пустого места внутри
страниц. Этот объем постоянно меняется: при добавлении новых
версий строк он уменьшается, при очистке — увеличивается.
Карта используется при вставке новых версий строк, чтобы быстро
найти подходящую страницу, на которую поместятся добавляемые
данные. Для ускорения поиска карта свободного пространства имеет
сложную древовидную структуру.
Карта свободного пространства может существовать и для индексов.
Но, поскольку индексная запись вставляется в строго определенное
место индекса, в карте отмечаются только пустые страницы,
образовавшиеся при удалении из них всех записей. Такие страницы
исключаются из индексной структуры и при необходимости
подключаются затем в подходящее место индекса.
6
Периодические задачи
Обновление статистики
используется оптимизатором запросов
вычисляется на основе случайной выборки
Для работы оптимизатора запросов необходима статистическая
информация («статистика») о данных, такая как количество строк
в таблицах и распределение данных в столбцах. Сбор статистики
называется анализом.
Для анализа из таблицы читается случайная выборка данных
определенного размера. Это позволяет быстро собрать информацию
даже по очень большим таблицам. Результат получается не точный,
но этого и не требуется. В любом случае данные все время изменяются
и постоянно поддерживать абсолютно точную статистику невозможно.
Достаточно, чтобы она периодически обновлялась и не слишком сильно
отличалась от действительности.
Если не обновлять статистику, она перестанет соответствовать
реальным данным и оптимизатор станет строить плохие планы
выполнения. Из-за этого запросы могут начать выполняться на порядки
медленнее, чем могли бы.
7
Периодические задачи
Заморозка
предотвращение последствий переполнения 32-битного
счетчика транзакций
Как уже говорилось, PostgreSQL упорядочивает события с помощью
номеров транзакций. Под счетчик отведено 32 бита и рано или поздно
он переполнится.
Чтобы многоверсионность продолжила работать, пространство номеров
закольцовано: для любой транзакции половина номеров против
часовой стрелки находится в прошлом, а другая половина —
в будущем.
Но если счетчик перейдет через ноль, упорядоченность транзакций
нарушится, если не принять специальных мер. Достаточно старые
версии строк помечаются как «замороженные». Такой признак говорит
о том, что версия строки появилась так давно, что номер создавшей ее
транзакции больше не имеет значения и его можно использовать
повторно. Замороженные версии строк видны во всех снимках всех
транзакций.
Чтобы при заморозке не просматривать лишние страницы, в карту
видимости добавлен бит, отмечающий страницы, на которых все версии
строк уже заморожены.
Если не выполнять заморозку своевременно, сервер не сможет
выделить очередной номер транзакции. Это аварийная ситуация:
сервер остановится, все незавершенные транзакции оборвутся.
После этого администратор должен будет вручную стартовать сервер
и выполнить заморозку.
8
Автоматическая очистка
Autovacuum launcher
фоновый процесс
периодически запускает
рабочие процессы
Autovacuum worker
очищает таблицы
отдельной базы данных,
требующие обработки
PostgreSQL
backend
postmaster
фоновые процессы
autovacuum
общая память
ОС
кеш
Выполнение всех описанных выше периодических задач обслуживания
берет на себя фоновый процесс автоочистки (autovacuum). Он
динамически реагирует на частоту обновления таблиц: чем активней
изменения, тем чаще таблица будет обрабатываться.
В системе постоянно присутствует процесс autovacuum launcher,
который планирует работу очистки и запускает необходимое число
рабочих процессов autovacuum worker, работающих параллельно.
Очистка работает постранично, не приводя к блокировкам других
транзакций, хотя и создает, конечно, нагрузку на подсистему ввода-
вывода.
Автоматическая очистка перестанет работать при отключении любого
из двух параметров autovacuum или track_counts. Может ошибочно
показаться, что отключение способно увеличить производительность
системы за счет исключения «лишних» операций ввода-вывода.
На самом деле отказ от очистки влечет за собой последствия,
описанные выше: неконтролируемое разрастание файлов, замедление
запросов и риск аварийной остановки сервера. В конечном итоге это
приведет к полному параличу системы.
Автоочистка должна работать. Она настраивается большим
количеством конфигурационных параметров; эта настройка детально
обсуждается в курсе DBA2 «Настройка и мониторинг».
9
Запуск вручную
Очистка
VACUUM [таблица, ...] очистка отдельных таблиц
VACUUM очистка всей БД
$ vacuumdb обертка для использования в ОС
Анализ
ANALYZE
$ vacuumdb --analyze-only
Очистка и анализ
VACUUM ANALYZE
$ vacuumdb --analyze
При необходимости очистку и анализ можно запускать вручную.
Для этого служат команды VACUUM (только очистка), ANALYZE (только
анализ), а также VACUUM ANALYZE (и очистка, и анализ).
Автоочистка отличается от запуска очистки и анализа по расписанию
тем, что реагирует на активность изменения данных. Слишком частый
запуск по расписанию создаст ненужную нагрузку на систему. Если же
запускать очистку редко, при большом объеме изменений файлы могут
успеть существенно вырасти в размерах.
11
Проблема разрастания
Очистка не уменьшает размер таблиц и индексов
«дыры» в страницах используются для новых данных,
но место не возвращается операционной системе
Причины разрастания
неправильная настройка автоочистки
массовое изменение данных
долгие транзакции
Негативное влияние
перерасход места на диске
замедление последовательного просмотра таблиц
уменьшение эффективности индексного доступа
Очистка вычищает неактуальные версии строк из страниц. В страницах
образуется свободное пространство, которое затем используется для
размещения новых данных. Но освободившееся место не
возвращается операционной системе, то есть с точки зрения ОС
размер файлов данных не уменьшается.
В случае индексов (B-деревьев) дело осложняется тем, что если на
странице не хватает места для размещения индексной записи,
страница расщепляется на две. Получившиеся страницы уже никогда
не объединяются, даже если из них будут удалены все индексные
записи.
При правильной настройке процесса автоочистки файлы данных
вырастают на некоторую постоянную величину за счет обновлений
между запусками очистки. Но если выполняется одномоментное
изменение большого объема данных или в системе присутствуют
долгие транзакции (удерживающие снимки данных и не позволяющие
вычищать неактуальные версии строк), очистка не сможет
своевременно освобождать место. В результате размер таблиц и
индексов может продолжать увеличиваться.
Разрастание файлов данных ведет не только к перерасходу места на
диске (в том числе и для резервных копий), но и к ухудшению
производительности.
13
Перестроение объектов
Полная очистка
VACUUM FULL
$ vacuumdb --full
полностью перестраивает содержимое таблиц и индексов
полностью блокирует работу с таблицей
Перестроение индексов
REINDEX
перестраивает индексы
полностью блокирует работу с индексом
и блокирует изменение таблицы
Для того чтобы уменьшить физический размер разросшихся таблиц
и индексов, требуется полная очистка.
Команда VACUUM FULL полностью перезаписывает содержимое
таблицы и ее индексов, минимизируя занимаемое место. Однако этот
процесс требует исключительной блокировки таблицы и поэтому не
может выполняться параллельно с другими транзакциями.
Можно перестроить один индекс или несколько индексов, не трогая
таблицу, — это делает команда REINDEX. Она устанавливает
блокировки на запись в таблицу и на использование перестраиваемого
индекса, поэтому транзакции, пытающиеся изменить таблицу или
планировать запрос к ней, будут приостановлены.
Если долгая исключительная блокировка нежелательна,
можно рассмотреть стороннее расширение pg_repack
https://github.com/reorg/pg_repack, позволяющее выполнить
перестроение таблицы и ее индексов «на лету».
14
Перестроение объектов
Неблокирующее перестроение индексов
REINDEX ... CONCURRENTLY
перестраивает индексы, не блокируя изменение таблицы
выполняется дольше и может завершиться неудачно
не транзакционно
не работает для системных индексов
не работает для индексов, связанных с ограничениями-исключениями
Команда REINDEX с указанием CONCURRENTLY работает без
блокировки таблицы на запись. Однако неблокирующее перестроение
выполняется дольше и может завершиться неудачно (из-за
взаимоблокировок) — в таком случае индекс потребуется еще раз
перестроить.
У неблокирующего перестроения индексов есть ряд ограничений. Такая
операция не может выполняться внутри транзакции. В неблокирующем
режиме нельзя перестроить системные индексы и индексы, связанные
с ограничениями-исключениями (EXCLUDE).
16
Итоги
Версии строк накапливаются, поэтому необходима
периодическая очистка
Процедура очистки решает много других задач:
обновление карт видимости и свободного пространства
сбор статистики для планировщика
заморозка старых версий строк
Автоочистка должна работать, но требует настройки
При разрастании может потребоваться полная очистка
17
Практика
1. Отключите процесс автоочистки и убедитесь, что он
не работает.
2. В новой базе данных создайте таблицу с одним числовым
столбцом и индекс по этой таблице. Вставьте в таблицу
100 000 случайных чисел.
3. Несколько раз измените половину строк таблицы,
контролируя на каждом шаге размер таблицы и индекса.
4. Выполните полную очистку.
5. Повторите действия пункта 3, вызывая после каждого
изменения обычную очистку. Сравните результаты.
6. Включите процесс автоочистки.
1. Установите параметр autovacuum в значение off и попросите сервер
перечитать файлы конфигурации.
3. Используйте функции pg_table_size(имя-таблицы) и
pg_indexes_size(имя-таблицы). Подробнее о функциях для
вычисления размеров различных объектов говорится в модуле
«Организация данных».
6. Установите параметр autovacuum в значение on (или сбросьте
значение этого параметра командой RESET), затем попросите сервер
перечитать файлы конфигурации.