- •Предисловие
- •Об этой книге
- •Глава 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
- •Предметный указатель
3.6. Сквозная идентификация с queryid |
91 |
Статистикапланированияивыполнения—этонеединственное,чтоестьвpg_stat_statements. В этом представлении также можно найти статистику ввода-вывода и записи WAL, однако ее рассмотрение мы продолжим в других главах.
3.6. Сквозная идентификация с queryid
Информацию по выполняемым в СУБД запросам можно получить из нескольких источников:
•pg_stat_activity—запросы,выполняемые в сеансах;
•pg_stat_statements—кумулятивная статистика по успешно выполненным запросам;
•журнал сообщений—запросы независимо от статуса их завершения (успех или ошибка);
•вывод команды EXPLAIN—план выполнения запроса.
Однако долгое время эти источники не были связаны друг c другом. Чтобы получить целостную картину о конкретном типе запроса, необходимо обработать данные из всех источников. Но в pg_stat_activity и журналах сообщений указываются полные тексты запросов, а в pg_stat_statements сохраняются нормализованные запросы, и сопоставить их было непростойзадачей.Расширениеpg_stat_statementsумеетрассчитыватьидентификаторзапроса queryid, и начиная с версии 14 этот идентификатор стал доступен в остальных источниках — теперь выполнять идентификацию запроса по всем возможным источникам стало гораздо проще.
Расчет идентификатора зависит от параметра compute_query_id. Значение по умолчанию auto разрешает расширению pg_stat_statements (и аналогичным) автоматически вычислять идентификаторы. При включении compute_query_id идентификатор запроса будет отображаться в pg_stat_activity, журналировании через csvlog (или при указании формата в log_line_prefix)
и в выводе EXPLAIN VERBOSE.
При реализации сквозной идентификации имена полей в представлениях получились разны-
ми—pg_stat_activity.query_id и pg_stat_statements.queryid.
3.7. Построение отчетов на основе pg_stat_statements
Для оценки эксплуатации системы за длительные периоды могут быть полезны сводные или суммарные отчеты. Как правило, эти отчеты в разных проекциях показывают, насколько эффективно система справляется с рабочей нагрузкой. С их помощью можно не только быстро оценить состояние системы, но и отследить динамику относительно предыдущих периодов. Такие отчеты можно строить на основе статистики по запросам из pg_stat_statements,учитывая ее накопительный характер.
92Глава 3. Выполнение запросов и функций
Концепция такого отчета довольно проста: нужно определить суммарное использование ресурсов по каждой проекции в pg_stat_statements и затем для каждого отдельного запроса определить его вклад в эту сумму. Полученные доли использования ресурсов следует отсортировать по какому-либо критерию,например,по суммарному времени выполнения запроса.
Примеры скриптов для создания подобных отчетов можно найти в репозитории DataEgret1. Отчет содержит список запросов, выполнение которых заняло больше всего времени, обогащенный подробной информацией из pg_stat_statements. Вот пример такого отчета по запросам в тестовом окружении:
# \i /var/lib/postgresql/scripts/query_stat_total.sql |
|
|
|
|||
Output format is unaligned. |
|
|
|
|
||
?column? |
|
|
|
|
|
|
total time: |
11:50:59 (IO: 1.29%) |
|
|
|
||
total queries: 25,411,617 (unique: 62) |
|
|
|
|||
report for all databases, version 0.9.5 @ PostgreSQL 15beta1 |
|
|
||||
tracking all 5000 queries, utilities on, logging 500ms+ queries |
|
|
||||
============================================================================================================= |
||||||
pos:1 |
total time: 05:12:05 (43.9%, CPU: 44.5%, IO: 0.0%) |
calls: 1,800,650 (7.09%) avg_time: 10.40ms (IO: 0.0%) |
||||
user: classic |
db: pgbench |
rows: 1,800,650 (8.37%) |
|
query: |
|
|
UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 |
|
|||||
============================================================================================================= |
||||||
pos:2 |
total time: 02:53:43 (24.4%, CPU: 24.8%, IO: 0.0%) |
calls: 996,873 (3.92%) |
avg_time: 10.46ms (IO: 0.0%) |
|||
user: maru |
db: pgbench |
rows: 996,873 (4.64%) |
query: |
|
|
|
UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 |
|
|||||
============================================================================================================= |
||||||
pos:3 |
total time: 00:50:08 (7.1%, CPU: 7.1%, IO: 0.0%) |
|
calls: 496,689 (1.95%) |
avg_time: 6.06ms (IO: 0.0%) |
||
user: pgbench |
db: pgbench |
rows: 496,689 (2.31%) |
query: |
|
|
|
UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2 |
|
|||||
... остальной вывод опущен ...
Отчет состоит из двух частей.Первая часть показывает общую информацию:
•суммарное время,затраченное на успешное выполнение всех запросов,причем отдельно отмечена доля ввода-вывода;
•общее количество успешно выполненных запросов с указанием количества уникальных типов запросов;
•версия отчета и версия PostgreSQL;
•настройки pg_stat_statements.
Втораячастьпоказываетзапросы,отсортированныепообщемувременивыполнения.Каждый запрос сопровождается дополнительной информацией:
1 github.com/dataegret/pg-utils/blob/master/sql/global_reports/query_stat_total_13.sql
3.7. Построение отчетов на основе pg_stat_statements |
93 |
•вклад запроса в общее время выполнения с разделением на CPU и ввод-вывод;
•количество вызовов запроса с указанием доли в общем объеме всех вызовов;
•среднее время выполнения запроса с отдельным учетом ввода-вывода;
•информация о пользователе,базе данных и количестве затронутых строк;
•нормализованный текст запроса.
Полученной информации достаточно,чтобы оценитьдоли запросов в рабочей нагрузке и при необходимости перейти к анализу производительности и рефакторингу.При желании скрипт можно модифицировать и добавить другую необходимую информацию, например период, за который взята статистика, идентификаторы запросов, использование ресурсов, объем сгенерированных журнальных записей и т. д.
В качестве другого примера можно взять вывод отчета из pgcenter, где для любого интересующего запроса из pg_stat_statements можно получить сводную информацию:
summary: |
|
|
|
|
|
total queries: 25,421,767 |
|
|
|
|
|
total rows: 21,512,607 |
|
|
|
|
|
total WAL: 25 GB |
|
|
|
|
|
total_time: 11:51:10, 100% |
|
|
|
|
|
total_plan_time: 00:26:34, |
3.74% |
|
|
|
|
total_cpu_time: 11:15:27, |
94.98% |
|
|
|
|
total_io_time: 00:09:08, |
1.29% |
|
|
|
|
query info: |
|
|
|
|
|
queryid: |
|
2368592290184574017 |
|||
username: |
|
classic, |
|
|
|
database: |
|
pgbench, |
|
|
|
calls (relative to total): |
|
1,801,358, |
7.09%, |
||
rows (relative to total): |
|
1,801,358, |
8.37%, |
||
WAL usage (relative to total): |
|
|
|
|
|
records: |
|
2,011,320, |
10.88% |
||
full-page images: |
|
849, 0.03% |
|
||
bytes: |
|
144 MB, |
0.56% |
|
|
total times (relative to total): |
05:12:10.007, |
43.89% |
|||
planning: |
|
00:01:40.461, |
6.30% |
||
cpu: |
|
05:10:29.546, |
45.97% |
||
io: |
|
00:00:00.000, |
0.00% |
||
average times (in-query distribution): 10.40ms, |
|
100% |
|
||
planning: |
|
0.06ms, |
0.54% |
|
|
cpu: |
|
10.34ms, |
|
99.46% |
|
io: |
|
0.00ms, |
0.00% |
|
|
query text:
UPDATE pgbench_branches SET bbalance = bbalance + $1 WHERE bid = $2
94Глава 3. Выполнение запросов и функций
Вфокусе отчета pgcenter находится всего лишь один выбранный запрос. В первой, верхней части отчета приведена сводная информация, а во второй части показаны статистика по выбранному запросу и его вклад в общую рабочую нагрузку:
•количество вызовов и затронутых строк с соответствующими долями;
•объем сгенерированных журнальных записей сдетализацией по количеству записей,бай-
там и FPI-страницам (см. full_page_writes1);
•суммарноевремявыполнениявсехзапросовэтоготипасдетализациейпопланированию, выполнению и вводу-выводу;
•среднее время выполнения запросов этого типа с детализацией;
•нормализованный текст запроса.
Сравнивая оба отчета, можно заметить, что они различаются предназначением. Отчет DataEgretпредлагаетболееполнуюкартинуотом,чтовыполняетсявСУБД,ибольшеподходитдля роли сводного отчета.Отчетpgcenter предлагаетоценку использования ресурсов конкретным запросом и больше ориентирован на оперативный анализ и выявление деталей по подозрительным запросам.
При построении подобных отчетов и расчете суммарного использования ресурсов важно помнить, что расширение pg_stat_statements может собирать статистику выполнения не только верхнеуровневых, но и вложенных запросов, и это поведение регулируется параметром pg_stat_statements.track. В случае более детального отслеживания со значением all есть риск посчитать часть статистики дважды, например, при наличии запросов с функциями, внутри которых выполняются другие запросы или функции. Подсчет общей статистики будет включать статистику как самой функции, так и всех вложенных в нее запросов, что может сильно исказить результат. Для исключения этой проблемы следует учитывать флаг toplevel, который указывает на уровень выполнения и помогает исключить вложенные запросы (toplevel = false).К сожалению,флаг toplevel появился в версии 14,поэтому в более ранних версиях для отчетов рекомендуется установить pg_stat_statements.track = top.
3.8. Представление pg_stat_statements_info
В дополнение к основному представлению у расширения есть еще одно небольшое служебное представление—pg_stat_statements_info,состоящее всего из одной строки с двумя полями:
•dealloc — количество раз, когда расширение было вынуждено частично удалить статистику из-за достижения ограничения pg_stat_statements.max. При этом возникает риск потери некоторой статистики, что может искажать данные отчетов. В качестве обходного
1 postgrespro.ru/docs/postgrespro/current/runtime-config-wal#GUC-FULL-PAGE-WRITES
