Архитектура
Очистка
12
Авторские права
© Postgres Professional, 2020 год.
Авторы: Егор Рогов, Павел Лузанов
Использование материалов курса
Некоммерческое использование материалов курса (презентации,
демонстрации) разрешается без ограничений. Коммерческое
использование возможно только с письменного разрешения компании
Postgres Professional. Запрещается внесение изменений в материалы
курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу:
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за
любые повреждения и убытки, включая потерю дохода, нанесенные
прямым или непрямым, специальным или случайным использованием
материалов курса. Компания Postgres Professional не предоставляет
каких-либо гарантий на материалы курса. Материалы курса
предоставляются на основе принципа «как есть» и компания Postgres
Professional не обязана предоставлять сопровождение, поддержку,
обновления, расширения и изменения.
2
Темы
Очистка версий строк и анализ таблиц
Заморозка версий строк
3
Очистка и анализ
Как устроен процесс очистки
Анализ таблиц
Полная очистка
4
Очистка
Выполняется командой VACUUM
очищает ненужные версии строк в табличных страницах
(пропуская страницы, уже отмеченные в карте видимости)
очищает индексные записи, ссылающиеся на очищенные версии строк
обновляет карты видимости и свободного пространства
Обычно работает в автоматическом режиме
частота обработки зависит от интенсивности изменений в таблице
процессы autovacuum launcher и autovacuum worker
Как мы уже знаем, для реализации многоверсионности в таблице
накапливаются исторические версии строк, а в индексах — ссылки на
такие исторические версии. Когда версия строки уходит за «горизонт»
базы данных, ее можно удалить, освобождая место для других версий.
Очистка, выполняемая командой VACUUM, обрабатывает всю таблицу,
включая все созданные на ней индексы. При этом удаляются и
ненужные версии строк, и указатели на них в начале страницы.
Обычно очистка запускается не вручную, а работает в автоматическом
режиме в зависимости от количества изменений в таблицах. Чем чаще
изменяются строки, тем чаще автоочистка обрабатывает таблицу и ее
индексы.
При включенной автоочистке в системе всегда присутствует процесс
autovacuum launcher, который занимается планированием работы.
Реальную очистку выполняют процессы autovacuum worker, несколько
экземпляров которых могут работать параллельно.
Важно, чтобы процесс автоочистки был правильно настроен. Как это
делается, рассматривается в курсе DBA2 «Администрирование
PostgreSQL. Настройка и мониторинг». Если автоочистка не будет
срабатывать вовремя, таблицы будут разрастаться в размерах. Кроме
того, важно, чтобы в системе, в которой данные активно изменяются
(OLTP), не было длинных транзакций, удерживающих горизонт базы
данных и мешающих очистке.
5
xmaxxmin данные
101 42,BAR102
Пример
100 42,FOO
ctid ключ
(0,2) BAR
(0,1) 101
(0,3) BAZ
(0,2)
(0,1) FOO
102 42,BAZ0(0,3)
Рассмотрим пример.
На рисунке приведена ситуация до очистки. В табличной странице три
версии одной строки. Две из них неактуальны, не видны ни в одном
снимке и могут быть удалены.
В индексе есть три ссылки на каждую из версий строки.
6
xmaxxmin данные
Фаза очистки индексов
ctid ключ
(0,3) BAZ
требуется полное
сканирование всех индексов,
созданных на таблице
101 42,BAR102
100 42,FOO(0,1) 101
(0,2)
102 42,BAZ0(0,3)
Очистка обрабатывает данные постранично. Таблица при этом может
использоваться обычным образом и для чтения, и для изменения
днако одновременное выполнение для таблицы таких команд, как
CREATE INDEX, ALTER TABLE и др. будет невозможно — подробнее
см. тему «Обзор блокировок»).
Сначала таблица сканируется в поисках версий строк, которые можно
очистить. Для этого (с помощью карты видимости) читаются только те
страницы, в которых происходила какая-то активность.
Идентификаторы очищаемых строк запоминаются.
Затем начинается фаза очистки индексов. Каждый из индексов,
созданных на таблице полностью сканируется в поисках записей,
которые ссылаются на очищаемые версии строк (это еще один повод не
создавать лишних индексов!). Найденные индексные записи
очищаются.
После этой фазы в индексе уже нет ссылок на устаревшие версии
строк, но сами версии строк еще присутствуют в таблице.
7
xmaxxmin данные
Фаза очистки таблицы
ctid ключ
(0,1)
(0,3) BAZ
(0,2)
102 42,BAZ0(0,3)
при большом объеме
очищаемых данных
потребуется повторить
весь процесс несколько раз
Затем выполняется фаза очистки таблицы. На этой фазе таблица снова
сканируется, и из нее вычищаются версии строк с запомненными ранее
идентификаторами.
После этой фазы устаревших версий строк нет ни в индексах, ни
в таблице.
Заметим, что фазы очистки индексов и таблицы могут поочередно
выполняться несколько раз, если не хватает памяти для того чтобы
сразу запомнить все идентификаторы очищаемых строк. Такой
ситуации стараются избегать правильной настройкой автоочистки.
В процессе очистки таблицы обновляются и карта видимости (если на
странице не остается неактуальных версий строк), и карта свободного
пространства, в которой отражается наличие свободного места
в страницах.
9
Анализ
Выполняется командой ANALYZE
собирает статистику для планировщика
можно вместе с очисткой командой VACUUM ANALYZE
Обычно работает в автоматическом режиме
вместе с автоматической очисткой
Еще одна задача, которую обычно совмещают с очисткой, — анализ,
то есть сбор статистической информации для планировщика запросов.
Анализируется число строк в таблице, распределение данных по
столбцам и т. п. Более подробно это рассматривается в курсе QPT
«Оптимизация запросов».
Вручную анализ выполняется командой ANALYZE (только анализ) или
VACUUM ANALYZE (и очистка, и анализ).
Обычно очистка и анализ запускаются не вручную, а работают вместе
в автоматическом режиме. Частота автоанализа также зависит от
интенсивности изменений и допускает тонкую настройку.
10
Полная очистка
Перестраивает файлы и возвращает место файловой системе
Команда VACUUM FULL
полностью перестраивает таблицу и все ее индексы
монопольно блокирует таблицу и ее индексы на все время работы
Команда REINDEX
полностью перестраивает только индексы
монопольно блокирует индекс и запрещает запись в таблицу
вариант REINDEX CONCURRENTLY не мешает чтению и записи,
но выполняется дольше
Обычная очистка не решает всех задач по освобождению места.
Если таблица или индекс сильно выросли в размерах, то очистка не
приведет к сокращению числа страниц (и к уменьшению файлов).
Вместо этого внутри существующих страниц появятся «дыры», которые
могут быть использованы для вставки новых строк или изменения
существующих. Единственно исключение составляют полностью
очищенные страницы, находящиеся в конце файла — такие страницы
«откусываются» и возвращаются операционной системе.
Если размер файлов превышает некие разумные пределы, можно
выполнить команду VACUUM FULL для полной очистки. При этом
таблица и все ее индексы перестраиваются полностью с нуля,
а данные упаковываются максимально компактно.
Полная очистка не предполагает регулярного использования, так как
полностью блокирует всякую работу с таблицей (включая и выполнение
запросов к ней) на все время своей работы.
Команда REINDEX перестраивает индексы, не трогая при этом таблицу.
Фактически, VACUUM FULL использует эту команду для того, чтобы
перестроить индексы. Вариант этой команды с ключевым словом
CONCURRENTLY работает дольше, но не блокирует индекс и не
мешает чтению и обновлению данных.
11
Пример
(0,1)
(0,2)
(0,3)
xmaxxmin данные
101 42,BAR102
100 42,FOO
ctid ключ
(0,2) BAR
101
(0,3) BAZ
(0,1) FOO
102 42,BAZ0
На рисунке приведена та же самая ситуация до очистки, которую мы
уже рассматривали.
В табличной странице три версии одной строки. Две из них
неактуальны, не видны ни в одном снимке и могут быть удалены.
В индексе есть три ссылки на каждую из версий строки.
12
xmaxxmin данные
После полной очистки
ctid ключ
(0,1) BAZ
(0,1) 102 42,BAZ0
После выполнения полной очистки файлы данных индекса и таблицы
перестроены заново, нумерация версий строк изменилась. В страницах
отсутствуют «дыры», данные упакованы максимально плотно.
14
Заморозка
Проблема переполнения счетчика транзакций
Заморозка версий строк
15
Переполнение счетчика
3
пространство номеров транзакций (32 бита) закольцовано
половина номеров — прошлое, половина — будущее
1
2
Под номер транзакции в PostgreSQL выделено 32 бита. Это довольно
большое число (около 4 млрд номеров), но при активной работе
сервера оно вполне может быть исчерпано. Например при нагрузке
1000 транзакций в секунду это произойдет всего через полтора месяца
непрерывной работы.
Но мы говорили о том, что механизм многоверсионности полагается на
последовательную нумерацию транзакций — из двух транзакций
транзакция с меньшим номером считается начавшейся раньше.
Понятно, что нельзя просто обнулить счетчик и продолжить нумерацию
заново.
Почему под номер транзакции не выделено 64 бита — ведь это
полностью исключило бы проблему? Дело в том, что (как
рассматривалось в теме «Обзор внутреннего устройства») в заголовке
каждой версии строки хранятся два номера транзакций — xmin и xmax.
Заголовок и так достаточно большой, а увеличение разрядности
привело бы к его увеличению еще на 8 байт.