- •Предисловие
- •Об этой книге
- •Глава 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
- •Предметный указатель
138Глава 5. Область общей памяти и ввод-вывод
•структуры,связанные с подсистемой уведомлений (команды LISTEN и NOTIFY);
•прочие структуры,использующие кеши на основе SLRU-алгоритма.
Для отслеживания использования SLRU-кешей применяется представление pg_stat_slru:
# SELECT * FROM pg_stat_slru; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
name |
| blks_zeroed | blks_hit | blks_read |
| blks_written | blks_exists | flushes |
| truncates | |
... |
||||||||||||
-----------------+-------------+----------+-----------+--------------+-------------+---------+-----------+---------- |
... |
|||||||||||||||
CommitTs |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
1424 |
| |
0 |
| 2022-11-0... |
|
MultiXactMember | |
1 |
| |
0 |
| |
0 |
| |
1 |
| |
0 |
| |
1424 |
| |
0 |
| 2022-11-0... |
||
MultiXactOffset |
| |
1 |
| |
1 |
| |
4 |
| |
5 |
| |
0 |
| |
1424 |
| |
0 |
| 2022-11-0... |
|
Notify |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| 2022-11-0... |
|
Serial |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| 2022-11-0... |
|
Subtrans |
| |
7522 |
| |
0 |
| |
0 |
| |
7462 |
| |
0 |
| |
1424 |
| |
0 |
| 2022-11-0... |
|
Xact |
| |
471 |
| 79554357 | |
48 |
| |
1889 |
| |
0 |
| |
1424 |
| |
0 |
| 2022-11-0... |
|||
other |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| |
0 |
| 2022-11-0... |
|
Каждая строка содержит накопленную статистику использования конкретного SLRU-кеша (список кешей фиксирован):
•name—название SLRU-кеша;
•blks_zeroed—количество блоков,заполненных нулями во время инициализации;
•blks_hit—количество блоков,найденных в кеше;
•blks_read— количество блоков, которые потребовалось прочитать из основного хранилища на диске;
•blks_written — количество грязных блоков, которые потребовалось записать из кеша на диск;
•blks_exists—количество блоков,успешно найденных на диске;
•flushes—количество выполненных запросов на синхронизацию грязных блоков;
•truncates— количество выполненных запросов на удаление блоков ввиду их ненужности (при операциях обслуживания);
•stats_reset—отметка времени последнего сброса статистики.
Статистика использования SLRU-кешей пока можетприменятьсятолькодля мониторинга,поскольку конфигурация СУБД не предусматривает параметров, позволяющих регулировать их размеры (однако не исключено, что такие параметры могут появиться в будущем). Основной сценарий использования статистики—это оценка эффективности кешей.
5.4. Ввод-вывод в контексте объектов СУБД
Статистикаpg_buffercache,рассмотреннаяранее,позволяетанализироватьтолькообщуюкартинуиспользованиябуферногокеша.Мониторингбуферногокешаспомощьюэтогопредстав- лениянедаетполнойинформацииобобъемеввода-вывода,посколькусодержитинформацию
5.4. Ввод-вывод в контексте объектов СУБД |
139 |
толькоотехобъектах,чтонаходятсявкешевданныймомент,иизполязренияможетпропасть множестводругихобъектовБД,доступккоторымосуществлялсямеждуснимкамистатистики. Для более полного учета ввода-вывода нужна статистика накопительного характера по всем объектам БД. Эта информация располагается в нескольких представлениях, с одним из которых нам уже приходилось сталкиваться:
•pg_stat_database содержит часть статистики ввода-вывода для отдельных баз данных;
•pg_statio_all_tables — статистика ввода-вывода по таблицам (включая TOAST и временные таблицы);
•pg_statio_all_indexes—статистика ввода-вывода по индексам;
•pg_statio_all_sequences—статистика ввода-вывода по последовательностям.
Базы данных
Представление pg_stat_database уже знакомо нам из предыдущих глав, и сейчас мы возвращаемся к нему, потому что оно содержит несколько полей с информацией о вводе-выводе
вразрезе отдельных баз данных:
•blks_hit—количество блоков,найденных в общем и локальных кешах;
•blks_read — количество блоков, прочитанных с диска (включая найденные в страничном кеше ОС);
•blk_read_time—время,затраченное на чтение с диска,в миллисекундах;
•blk_write_time—время,затраченное на запись на диск,в миллисекундах.
Учет времени доступен только при включенном параметре track_io_timing. Для полноты картины не хватаеттолько статистики по записанным и грязным блокам.На основе этих данных можно получить общее представление об эффективности использования кеша, однако важно помнить, что статистика содержит данные как по общему,так и по локальным кешам, что имеет особое значение при широком использовании временных таблиц.
Оценить эффективность и посчитать коэффициент попаданий в кеш можно следующим запросом:
#SELECT sum(blks_hit) / sum(blks_hit + blks_read) AS hit_ratio FROM pg_stat_database;
hit_ratio
------------------------
0.98473387049692560384
Полученнаяметрикапоказывает,насколькоэффективноиспользуетсякеш.Значения,близкие к единице, говорят о том, что нужные данные успешно обнаруживаются в кеше. И наоборот, чемближезначениякнулю,темреженужныеданныеобнаруживаютсявкешеитемчащеСУБД приходится обращаться к основному хранилищу, чтобы прочитать данные и затем загрузить
140Глава 5. Область общей памяти и ввод-вывод
их в кеш, при этом вытесняя из кеша другие данные. При постоянной низкой эффективности кешамноговременитратитсянадисковыйввод-вывод,иэтонегативносказываетсянаобщей производительности. К сожалению, здесь нет простого или универсального решения, и повысить эффективность кеша можно разными способами. Самый очевидный — это увеличение общего кеша, однако такой способ не всегда приводит к успеху. Более правильным способом является выявление тех запросов, которые осуществляют бóльшую часть ввода-вывода или тратят на это значительное время,и попытка их оптимизации (с помощью рефакторинга или добавления индексов).За счеттакой оптимизации можно в десятки и сотни раз улучшить производительность запросов и увеличить эффективность использования кеша, не прибегая к изменению конфигурации.
Еще один способ использования статистики — это отслеживание времени, затраченного на ввод-вывод,с помощью blk_read_time и blk_write_time (рис. 5.2):
Рис. 5.2.Время,затраченное на чтение и запись блоков
ТакойграфикхорошоподходитдляобщейоценкисостоянияСУБДиотражаетмоменты,когда СУБД была вынуждена тратить время на чтение и запись, в результате чего могли возникать просадки производительности при выполнении запросов.
Таблицы,индексы и последовательности
Дляполученияболеедетальнойинформацииопроисходящемвводе-выводенауровнеотдель- ных объектов СУБД можно воспользоваться следующими представлениями:
•pg_statio_all_tables содержит статистику по каждой таблице:
—heap_blks_read—количество блоков,прочитанных с диска;
—heap_blks_hit—количество блоков,найденных в кеше;
—idx_blks_read—количество блоков всех индексов,принадлежащих этойтаблице,прочитанных с диска;
5.4. Ввод-вывод в контексте объектов СУБД |
141 |
—idx_blks_hit — количество блоков всех индексов, принадлежащих этой таблице, найденных в кеше;
—toast_blks_read—количество блоков TOAST-таблицы,прочитанных с диска;
—toast_blks_hit—количество блоков TOAST-таблицы,найденных в кеше;
—tidx_blks_read—количество блоков индексов TOAST-таблицы,прочитанных с диска;
—tidx_blks_hit—количество блоков индексов TOAST-таблицы,найденных в кеше.
•pg_statio_all_indexes содержит статистику по каждому индексу:
—idx_blks_read—количество блоков,прочитанных с диска;
—idx_blks_hit—количество блоков,найденных в кеше.
•pg_statio_all_sequences содержит статистику по каждой последовательности:
—blks_read—количество блоков,прочитанных с диска;
—blks_hit—количество блоков,найденных в кеше.
Перечисленные представления содержат статистику по всем объектам, включая пользовательские и системные (которые принадлежат системному каталогу). Раздельную статистику по пользовательским и системным объектам можно найти в представлениях с префиксами pg_statio_sys_ и pg_statio_user_.
Отдельного внимания заслуживает статистика попаданий в кеш (поля с суффиксом _hit). Когда блок найден в буферном кеше,ввода-вывода не происходит: блок уже находится в памяти, принадлежащей СУБД, так что достаточно прочитать в буфере нужную строку или даже ее часть. Важно понимать что статистика попаданий в кеш показывает объем найденных в кешеданных,но при этом реальный объем потребовавшихсяданных можетбытьменьшим.При организации мониторинга нужно стараться избегать попыток прямого сравнения попаданий
вкеш с объемом чтения и особенно представления обоих значений в байтах. Для оценки эффективности кеша лучше оценивать отношение попаданий в кеш к общему количеству обращенийкданным(попаданиямвкешичтениямизхранилища).Тожесамоесправедливоивотношениистатистикизагрязнениябуферовизаписистраниц(поляblks_dirtiedиblks_written
впредставлении pg_stat_statements): загрязнение блока при вставке, обновлении или удалении отдельных строк является лишь частичным изменением буфера и не приводит к вводувыводу в отличие от записи блока непосредственно в основное хранилище.Этот нюанс важно учитыватьприсведенииметрикводинграфикиливычисленииобъемовввода-выводаприсо- ставлении отчетов производительности и при выборе общих единиц измерения (блоков или байтов).
Другое важное замечание относится к индивидуальности этой статистики — базы данных являются своего рода изолированными контейнерами для таблиц, индексов и прочих объектов. Следовательно,представления содержат статистикутолько потем объектам,которые принадлежат этой базе данных. Для сбора статистики по всем объектам в кластере баз данных необходимо подключаться по очереди к каждой отдельной БД.
142Глава 5. Область общей памяти и ввод-вывод
Статистика по отдельным объектамдаетдетальную информацию по вводу-выводу,но обычно она требуется в исключительных случаях оптимизации или поиска узких мест в производительности. За годы моей практики случаи, когда требовалась такая подробная информация, можно пересчитать по пальцам одной руки. Во многих производственных окружениях можетбытьбольшоеколичествобаз,таблицииндексов.Мониторингбудетпроизводитьбольшой объем метрик,перед сбором и хранением которых важно оценить их практическую ценность.
Следующим запросом можно получить объем чтения, который приходится на таблицы базы
(рис. 5.3 и 5.4):
# sum by (table) (rate(postgres_table_io_blocks_total{service_id="primary",access="read"}[1m]))
Рис. 5.3.Объем чтения по таблицам
Рис. 5.4.Объем чтения таблицы pgbench_history
