- •Предисловие
- •Об этой книге
- •Глава 1. Обзор статистики
- •Внутреннее устройство PostgreSQL
- •Установка соединений и работа сеансов
- •Запросы как базовая единица рабочей нагрузки
- •Планирование и выполнение запросов
- •Ввод-вывод при выполнении запросов
- •Журнал сообщений СУБД
- •Репликация изменений
- •Архивирование журнала предзаписи
- •Фоновая синхронизация данных
- •Автоочистка
- •Интерфейс статистики
- •Статистика как отправная точка инструментов мониторинга
- •Особенности статистики
- •Тестовое окружение
- •Глава 2. Статистика активности
- •Ключ к пониманию происходящего в СУБД
- •Взаимодействие клиента и сервера
- •Источники информации об активности
- •Представление pg_stat_activity
- •Представление pg_locks
- •Особенности pg_stat_activity и pg_locks
- •Представление pg_stat_database
- •Подключенные клиенты
- •Отслеживание клиентских сеансов
- •Транзакционная активность
- •Статусы завершения сеансов
- •Состояния сеансов
- •Отслеживание состояний
- •Ожидания и блокировки
- •Отслеживание состояний с учетом ожиданий
- •Взаимоблокировки
- •Бездействующие транзакции
- •Время выполнения запросов и транзакций
- •Отслеживание времени ожидания блокировок
- •Использование pg_locks.waitstart
- •Использование pg_stat_activity.state_change
- •Дерево блокировок
- •Глава 3. Выполнение запросов и функций
- •Зачем нужен мониторинг запросов
- •Расширение pg_stat_statements
- •Метаданные запроса
- •Планирование запроса
- •Исполнение запроса
- •Сквозная идентификация с queryid
- •Построение отчетов на основе pg_stat_statements
- •Представление pg_stat_statements_info
- •Выполнение процедур и функций
- •Глава 4. Базы данных
- •Иерархия объектов СУБД
- •Кластер баз данных
- •Табличные пространства
- •Базы данных
- •Схемы
- •Таблицы и индексы
- •TOAST
- •События в кластере баз данных
- •Рабочая нагрузка в отношении таблиц и индексов
- •Ошибки и нежелательные события
- •Функции для работы с объектами СУБД
- •Определение размеров объектов СУБД
- •Размещение объектов в файловой системе
- •Глава 5. Область общей памяти и ввод-вывод
- •Анализ общей памяти
- •Представление pg_buffercache
- •Представление pg_shmem_allocations
- •Анализ памяти клиентских процессов
- •Оценка использования SLRU-кешей
- •Ввод-вывод в контексте объектов СУБД
- •Базы данных
- •Ввод-вывод в контексте выполнения запросов
- •Временные файлы
- •Уровень баз данных
- •Ввод-вывод при выполнении запросов
- •Отслеживание в журнале сообщений
- •Отслеживание активных временных файлов
- •Ввод-вывод фоновых процессов
- •Глава 6. Журнал упреждающей записи
- •Отслеживание активности в журнале
- •Представление pg_stat_wal
- •Представление pg_stat_statements
- •Архивирование журнала
- •Представление pg_stat_archiver
- •Очередь архивирования
- •Глава 7. Репликация
- •Обзор репликации
- •Инструменты отслеживания репликации
- •Представление pg_stat_replication
- •Представление pg_stat_wal_receiver
- •Cлоты репликации и pg_replication_slots
- •Публикации и подписки
- •Конфликты восстановления
- •Глава 8. Очистка
- •Введение в очистку
- •Особенности очистки на практике
- •Когда выполняется автоочистка?
- •Статистика выполнения очистки
- •Счетчик транзакций и предотвращение ошибок, связанных с его зацикливанием
- •Раздувание таблиц и индексов
- •Отслеживание активных процессов очистки
- •Представление pg_stat_activity
- •Представление pg_stat_progress_vacuum
- •Глава 9. Ход выполнения операций
- •Представление pg_stat_progress_analyze
- •Представление pg_stat_progress_basebackup
- •Представление pg_stat_progress_cluster
- •Представление pg_stat_progress_create_index
- •Представление pg_stat_progress_copy
- •Предметный указатель
210 Глава 8. Очистка
ПримернозатримиллионатранзакцийдоисчерпанияидентификаторовСУБДпереходитврежим только чтения. Любая попытка выполнить запись или изменение данных завершится ошибкой.
ERROR: database is not accepting commands to avoid wraparound data loss in database "postgres"
HINT: Stop the postmaster and vacuum that database in single-user mode.
You might also need to commit or roll back old prepared transactions, or drop stale replication slots.
Такая ситуация расценивается как опасная и переход СУБД в аварийный режим исключает возможность продолжить работу и повредить данные. Для восстановления и продолжения нормальной работы администратору придется перезапустить СУБД в особом, однопользовательском режиме (single-user mode), выполнить очистку в тех БД, где это необходимо, после чего перезапустить СУБД в обычном режиме.
8.4. Раздувание таблиц и индексов
Устаревшие версии строк появляются в результате операций обновления или удаления. При нормальной работе занимаемоетакими версиями место оперативно освобождается очисткой и используется для вставки новых версий. Однако если устаревших версий накопилось слишком много и автоочистка долгое время не имела возможности вычищать их,то после очистки
вфайлах таблицы и индексов образуются большие свободные участки, которые, возможно, не израсходуются в дальнейшем и будут просто занимать место на диске. В результате дисковое пространство используется неэффективно. Стоит отдельно отметить, что это относится к «пустотам», находящимся в начале или середине файла: если очистка освобождает место
вконце файла,она может попытаться сделать усечение файла.
При продолжительной эксплуатации СУБД таких пустот в таблицах и индексах может образовываться все больше и больше, и происходит так называемое раздувание. Если сложить все эти пустоты вместе, может получиться внушительная цифра. С точки зрения эксплуатации необходимо регулярно проверять таблицы и индексы на предмет раздувания, выполнять их обслуживание и высвобождать неиспользуемое пространство.
Для поиска раздутых объектов наиболее эффективным и точным средством оценки является расширение pgstattuple1. Однако ценой точности являются большие накладные расходы: расширение читает каждую страницу проверяемого объекта, что требует соответствующего ввода-вывода и нагружает дисковую подсистему. Учитывая, что СУБД не имеет встроенных механизмов ограничения пропускной способности,такая «проверка» может значительно
1 postgrespro.ru/docs/postgresql/current/pgstattuple
8.4. Раздувание таблиц и индексов |
211 |
загрузить подсистему хранения и существенно повлиять на производительность конкурентно выполняющихся запросов. Поэтому регулярное и частое использование pgstattuple, например в агентах сбора телеметрии, может быть нежелательно; рекомендуется использовать pgstattuple только при необходимости.
Есть и другие, эвристические способы оценки с использованием данных из системного каталога, учитывающие общее количество строк, их ширину и другие особенности хранения, но,как правило,такие способы менееточны и могутдавать значительные отклонения.Выбор инструмента всегда остается за администратором и должен основываться на условиях эксплуатации. Примеры таких запросов можно найти в соответствующем разделе PostgreSQL Wiki1.
В целях ознакомления расширение pgstattuple установлено в тестовом окружении и с его помощью мы оценим раздувание двух таблиц: pgbench_accounts и маленькой pgbench_branches.
# SELECT * FROM pgstattuple('pgbench_accounts');
-[ RECORD 1 ]------ |
+---------------------------- |
table_len |
| 294264832 |
tuple_count |
| 2000000 |
tuple_len |
| 242000000 |
tuple_percent |
| 82.24 |
dead_tuple_count |
| 80131 |
dead_tuple_len |
| 9695851 |
dead_tuple_percent |
| 3.29 |
free_space |
| 10538908 |
free_percent |
| 3.58 |
# SELECT * FROM pgstattuple('pgbench_branches');
-[ RECORD 1 ]------ |
+---------------------------- |
table_len |
| 311296 |
tuple_count |
| 21 |
tuple_len |
| 672 |
tuple_percent |
| 0.22 |
dead_tuple_count |
| 959 |
dead_tuple_len |
| 30688 |
dead_tuple_percent |
| 9.86 |
free_space |
| 274084 |
free_percent |
| 88.05 |
Время выполнения запроса зависит от размера таблицы, так как необходимо прочитать каждый ее блок, поэтому оценка pgbench_accounts выполнялась дольше, чем оценка pgbench_branches. В результате анализа таблиц доступна следующая информация, по которой можно оценить раздувание:
•table_len—размер объекта (таблицы или индекса) в байтах;
•tuple_count—общее количество живых версий строк;
1 wiki.postgresql.org/wiki/Show_database_bloat
212Глава 8. Очистка
•tuple_len—общий размер живых версий строк в байтах;
•tuple_percent—процент живых версий строк от общего числа всех версий;
•dead_tuple_count—общее количество мертвых версий строк;
•dead_tuple_len—общий размер мертвых версий строк в байтах;
•dead_tuple_percent—процент мертвых версий строк от общего числа всех версий;
•free_space — общий размер в байтах свободного пространства внутри файлов таблицы, за счет которого раздулась таблица. Это пространство появляется как результат очистки отмертвыхверсийстрокидоступнодляповторногоиспользованиятольковэтойтаблице;
•free_percent — доля свободного пространства от общего размера объекта — то же самое раздутие,выраженное в процентах.
Наиболее интересными полями являются free_space и free_percent, поскольку прямо указывают объемы пустого пространства. Если сравнить статистику обеих таблиц, можно отметить, что таблица pgbench_accounts подвержена раздуванию гораздо меньше,чем pgbench_branches, 3,5% против 88%, но таблица pgbench_branches занимает всего 311 КБ. При высвобождении свободного места выигрыш может быть небольшим, однако если с этой таблицей связан значительный ввод-вывод,то можно существенно сократить накладные расходы.
В продолжение нашего примера выполним команду полной очистки VACUUM FULL для таблицы pgbench_branches.Этохотьиблокирующаяоперация,новыполнитсяонамгновенно,поскольку целевая таблица небольшая и содержит всего 20 строк.После операции полной очистки снова посмотрим статистику pgstattuple:
#VACUUM FULL pgbench_branches;
#SELECT * FROM pgstattuple('pgbench_branches');
-[ RECORD 1 ]------+----------------------------
table_len |
| 8192 |
tuple_count |
| 20 |
tuple_len |
| 640 |
tuple_percent |
| 7.81 |
dead_tuple_count |
| 88 |
dead_tuple_len |
| 2816 |
dead_tuple_percent |
| 34.38 |
free_space |
| 4276 |
free_percent |
| 52.2 |
Высвободилось практически все свободное место,а таблица стала умещаться в одну страницу размером 8 КБ.Однако это всеголишьнебольшаятаблица втестовом окружении.В настоящих производственных окружениях значения и результаты будут совершенно иными.
На практике для высвобождения пространства используются различные инструменты. Для индексов подходит использование команды REINDEX CONCURRENTLY, которая в неблокирующем режиме создает новый индекс и затем подменяет им старый. Для обработки таблиц СУБД
