Как стать автором
Обновить
375.96

Что в черном ящике, или Как разработчику понять, что требует оптимизации в БД PostgreSQL

Уровень сложностиПростой
Время на прочтение20 мин
Количество просмотров10K

Привет! Меня зовут Дмитрий Руденко, я из команды Databases Т-Банка.В последние годы наблюдается тенденция к переходу на Postgres со стороны многих команд и компаний, что приводит к увеличению количества Postgres-баз данных, требующих эффективного мониторинга и управления. 

Мы достигли впечатляющего масштаба — почти 10 000 работающих экземпляров PostgreSQL, с которыми работают более 2 000 команд. Каждый из этих инстансов обслуживает уникальные рабочие нагрузки, разработанные командами с различными подходами к архитектуре, используемыми фреймворками и паттернами проектирования. Несмотря на огромное количество БД, команда администраторов баз данных (DBA) остается относительно небольшой (10 человек). Это создает целый ряд сложных задач, требующих тщательного управления и оптимизации процессов.

В прошлом году мы завороженно следили за приближением цунами из миксов обслуживания, исследований, вопросов, загадок да еще к тому же щедро приправленных пугающими сбоями во всякого рода критичных системах. 

Что делать, когда на тебя надвигается вал работы? Правильно, нужно ее кому-нибудь делегировать.  Делегировать решили разработчикам. Они гораздо более сведущи в используемых ими подходах, знают больше об их структурах данных, знают узкие и критичные места. Надо просто помочь им увидеть, что же именно происходит в черном ящике БД Postgres.

Мы пришли к созданию общей системы мониторинга баз данных Postgres, предоставляющей пользователю в простом и понятном виде данные о состоянии инстанса. В этой статье я расскажу о нашем видении визуального представления информации для пользователя и о созданной нами группе дашбордов для наблюдения за базами данными Postgres. Вы увидите, что накопительная статистика Postgres совместно с Prometheus и Grafana способны творить чудеса. 

Административный дашборд

Начнем, пожалуй, с дашборда, предназначенного для нас — администраторов всего парка Postgres, ибо он является отличной начальной точкой для экскурсии по всем нашим пунктам наблюдения за работой PostgreSQL.

На административном дашборде мы собираем все проблемные инстансы (под инстансом здесь и далее подразумевается кластер Patroni).

Дашборд с проблемными инстансами, данные разделены по уровню критичности
Дашборд с проблемными инстансами, данные разделены по уровню критичности

На дашборде видим сборную информацию обо всех инстансах, которые за выбранный период испытывали проблемы с доступностью или на которых произошли failover или switchover. Имена инстансов — линки для перехода на подробные дашборды.

Ниже по дашборду расположена панель с картой доступности хостов.

Значение в ячейке определяет, сколько суммарно времени на данном интервале хост был доступен (1 — доступен все время, 0 — полностью недоступен)
Значение в ячейке определяет, сколько суммарно времени на данном интервале хост был доступен (1 — доступен все время, 0 — полностью недоступен)
Таблица с подробной информацией о хостах
Таблица с подробной информацией о хостах

В таблице можно увидеть уровень критичности, имя инстанса (соответствует кластеру Patroni), хост и его роль, некоторые метрики и описания хоста. Суммарное время недоступности отображается в поле total_time. Очень удобно, что можно быстро перейти к детальным дашбордам по проблемному хосту. По клику на instance_name мы переходим в дашборд по всему кластеру (DB General), по клику на host — в детальный дашборд по хосту (Host details).

На отдельной панели можно увидеть ситуацию с failover и switchover инстансов. 

Список проблемных инстансов в таблице временных отсчетов и в графическом представлении
Список проблемных инстансов в таблице временных отсчетов и в графическом представлении

Еще мы собрали топовые инстансы по утилизации ЦПУ, дискового пространства и распухшим wal. Эти секции помогают нам отслеживать инстансы с резкими деградациями производительности, инстансы, приближающиеся к дисковому лимиту, и инстансы с большими pg_wal-директориями (появляющимися чаще всего из-за залипших слотов репликации).

Проблемные хосты
Проблемные хосты

Раскрыта секция со списком хостов с высокой общей утилизацией ЦПУ. В таблице можно увидеть основные характеристики, роль хоста в кластере Patroni, текущую утилизацию ЦПУ. По кликам на имени хоста и инстанса можно перейти на детальные дашборды.

Администраторы могут быстро находить проблемные инстансы и переходить в дашборды с детальной информацией по ним. Эти дашборды предназначены также и для разработчиков, поэтому для них мы подготовили документацию. Для каждого графика есть ссылка на подробное описание и его особенности: на что обращать внимание, возможные кейсы и так далее.

Каждая панель имеет линк на соответствующий подраздел в документации
Каждая панель имеет линк на соответствующий подраздел в документации

Все эти дашборды организованы одинаково: слева — список меню для перехода по различным разделам, справа — графики. 

Первый пункт меню — логи, без них не обходится ни одно расследование. Следом идет обзорный дашборд по всему кластеру.

Дашборд DB General

DB General показывает хосты и их роли в кластере Patroni, некоторые характеристики сервера, утилизации, wal, лаги репликации. Справа — график доступности. Слева подсвечивается, прямо на уровне меню (и, соответственно, этот сигнал виден на всех дашбордах), опасное приближение к исчерпанию доступного места. 

Видно, что с 00:00 инстанс изрядно шатает. Кроме того, общий размер занятого места превысил 90% допустимого
Видно, что с 00:00 инстанс изрядно шатает. Кроме того, общий размер занятого места превысил 90% допустимого

Ниже по дашборду можно увидеть изменение ролей во времени и детальную информацию по хостам, представленным отдельными row. По каждому хосту можно видеть утилизации и сводные данные о нагрузках. Еще ниже — параметры pg_settings (для реплик показываются только расхождения с лидером)

Переключения ролей в кластере Patroni. Раскрытая секция с метриками лидера — утилизация ЦПУ, память, утилизация IO
Переключения ролей в кластере Patroni. Раскрытая секция с метриками лидера — утилизация ЦПУ, память, утилизация IO
Суммарное количество подключений, транзакционная и модификационная активность на лидере. Параметры pg_settings-лидера.
Суммарное количество подключений, транзакционная и модификационная активность на лидере. Параметры pg_settings-лидера.

В DB General представлена самая общая информация. Для более детального исследования предназначены еще несколько дашбордов. 

Узкоспециализированные дашборды

Сначала очень кратко рассмотрим небольшие узкоспециализированные дашборды DB Connections, DB Size, Host details, Health map и Troubleshooting, а затем подробно мощный DB Performance.

Дашборд DbConnection показывает подключения к бд Postgres и некоторые метрики сессий.

Графики общего количества подключений и активных сессий. Распределение подключений по состоянию, по базам данных, по пользователям. Графики длительных транзакций
Графики общего количества подключений и активных сессий. Распределение подключений по состоянию, по базам данных, по пользователям. Графики длительных транзакций

Дашборд DbSize показывает размер базы и ее составляющих.

Дашборд DB Size. Все о занимаемых размерах
Дашборд DB Size. Все о занимаемых размерах

На дашборде видно процент общего занятого места от лимита, распределение занятого места по базам данных, графики занимаемого места по директориям (удобно отслеживать распухание логов и wal журналов), отдельно для каждого участника кластера Patroni. График динамики размеров топовых объектов базы данных.

Дашборд HostDetails — здесь отображается детальная информация о хостах кластера Patroni. 

Роль хоста и его основные характеристики, метрики и графики ЦПУ, памяти, дисковой подсистемы
Роль хоста и его основные характеристики, метрики и графики ЦПУ, памяти, дисковой подсистемы

В Health map собраны различные индикаторы проблем с инстансом, а в Troubleshooting сконцентрирована только самая важная информация, помогающая определить источник проблемы во время сбоя. Они предназначены в основном для администраторов.

Health map - индикаторы для администраторов.
Health map - индикаторы для администраторов.
Troubleshooting - микс самых важных метрик для просмотра во время сбоев.
Troubleshooting - микс самых важных метрик для просмотра во время сбоев.

Дашборд Performance

Performance — вишенка на торте, большой и навороченный дашборд, главный помощник при определении узких мест с производительностью базы данных.  

В дашборде несколько больших секций 
В дашборде несколько больших секций 

По умолчанию развернута секция Overview. 

Утилизации ЦПУ, IO. Активность сессий. Транзакционная и модификационная активность. Длительные транзакции, заблокированные транзакции, дедлоки. Эффективность доступа к данным. Попадания в кэш. Временные файлы. Индикаторы сессий и фоновых процессов
Утилизации ЦПУ, IO. Активность сессий. Транзакционная и модификационная активность. Длительные транзакции, заблокированные транзакции, дедлоки. Эффективность доступа к данным. Попадания в кэш. Временные файлы. Индикаторы сессий и фоновых процессов

Overview позволяет одним взглядом оценить ситуацию в выбранный момент времени. Каждая панель состоит из индикатора, агрегирующего соответствующие метрики, и графика, на котором можно видеть динамику происходящего. На многие индикаторы настроены линки для перехода к просмотру логов. Например, при обнаружении дедлока можно кликнуть на красный индикатор и увидеть развернутую информацию о событии.

Ожидания и дедлоки
Ожидания и дедлоки
Sage — внутрибанковский инструмент для хранения и работы с логами
Sage — внутрибанковский инструмент для хранения и работы с логами

Индикаторы Maintenance помогают определить, выполнялись ли в указанном диапазоне времени какие-либо фоновые обслуживающие процессы, ручные запуски вакуума, не проводились ли тяжелые процессы создания пользователем индекса. 

Цвет индикатора указывает на тяжесть данной операции. Это важно, потому что некоторые из этих процессов могут играть катастрофическую роль в общей производительности. 
Цвет индикатора указывает на тяжесть данной операции. Это важно, потому что некоторые из этих процессов могут играть катастрофическую роль в общей производительности. 

Когда мы исследуем какую-либо проблему, желательно сразу же видеть, что у нас творилось в этот момент в фоне. Если в это время работал «агрессивный» сборщик мусора, то с большой долей вероятности можно предположить, что именно он повлиял на общую просадку производительности. 

Бросив взгляд на секцию Overview, мы по паттерну красных областей сразу понимаем, куда нужно копать. Ниже расположено много важных секций. На некоторых мы остановимся подробнее.

Секция Database — первая из свернутых по умолчанию секций дашборда Performance. В ней находится общая информация, нагрузки, ошибки, работа с диском, попадания в кэш и так далее. Метрики собираются с pg_stat_database.

Модификационная активность. Коммиты и роллбеки. Ошибки. Время записи и чтения блоков. Попадания в кэш. Объем данных, записанных во временные файлы
Модификационная активность. Коммиты и роллбеки. Ошибки. Время записи и чтения блоков. Попадания в кэш. Объем данных, записанных во временные файлы

Секция Sessions — одна из важнейших и полезных секций. В ней отражены метрики, собранные с представления pg_stat_activity. 

Ожидающие сессии. Активные сессии. Скорость создания и завершения с ошибками
Ожидающие сессии. Активные сессии. Скорость создания и завершения с ошибками
Общая длительность ожиданий сессий по событиям ожиданий. Распределение количества ожидающих сессий по событиям ожиданий
Общая длительность ожиданий сессий по событиям ожиданий. Распределение количества ожидающих сессий по событиям ожиданий

Хорошо видно, как запустившийся автовакуум привел к росту общего времени проведенного в ожидании и количества сессий, ожидающих IO:DataFileRead.

Ну и главный свидетель (мое любимое в этой секции) — таблица активности сессий. Зачастую здесь можно обнаружить каких-либо нарушителей порядка. 

Можно увидеть, кто, когда и какие запросы выполнял. Статусы, типы и события ожидания, временная статистика. Текст запроса раскрывается, только если его длительность начала превышать 1 минуту, это сделано для уменьшения кардинальности метрик
Можно увидеть, кто, когда и какие запросы выполнял. Статусы, типы и события ожидания, временная статистика. Текст запроса раскрывается, только если его длительность начала превышать 1 минуту, это сделано для уменьшения кардинальности метрик

Секция Locks — раздел, посвященный блокировкам. Метрики, собранные с представления pg_locks. 

Распределения по типам блокировок
Распределения по типам блокировок

В тяжелых случаях, когда запрос находится в блокировке дольше минуты, внизу выстраивается дерево Lock tree, по которому легко можно определить, кто виновник всей этой вакханалии (узнать pid процесса, удерживающего корневую блокировку).

Секция Checkpoints & Bgwriter предназначена для наблюдения за процессами checkpoints и background writer (метрикам, собранным с представления pg_stat_bgwriter). Позволяет оценить работу и корректность настроек этих процессов.

События записи контрольной точки, сверху можно видеть тип (запись по требованию выделяется красными отметками) и работа процесса фоновой записи
События записи контрольной точки, сверху можно видеть тип (запись по требованию выделяется красными отметками) и работа процесса фоновой записи

Секция Wal позволяет оценивать интенсивность записи Wal журналов (метрики, собранные с представления pg_stat_wal) и их архивацию (pg_stat_archiver). 

Объемы записи Wal журналов. Статистика процесса архивации
Объемы записи Wal журналов. Статистика процесса архивации

Секция Replication предоставляет важные данные о состоянии потоковой репликации и помогает выявлять потенциальные проблемы, связанные с репликацией. 

Отставание физической репликации (мастер → синхронная реплика) в мегабайтах и статус слота физической репликации
Отставание физической репликации (мастер → синхронная реплика) в мегабайтах и статус слота физической репликации
Отставание логической репликации в мегабайтах и статус слота логической репликации
Отставание логической репликации в мегабайтах и статус слота логической репликации

Секция Vacuum & Analyze важна для наблюдения за процессами вакуума (метрики, собранные с представлений pg_stat_progress_vacuum, pg_stat_progress_analyze). 

Postgres при обновлении записи создает новую версию. Старая версия какое-то время может быть видима для каких-то транзакций, но потом теряет актуальность и просто занимает место. Со временем таких строк становится все больше, и наступает момент, когда для добавления новой записи приходится создавать новую страницу. 

Postgres может сам определять, когда пора вызывать сборщик мусора, или можно сделать это вручную. Сборщик убирает старые версии, но место при этом не освобождается, таблица остается такой же распухшей. Чтобы вернуть место на дисках операционной системе, используется vacuum full, который заново перестраивает всю таблицу. На дашборде с деталями по таблице (мы подробнее рассмотрим ее далее) хорошо видно все три этапа.

Темная область — это старые версии, сборщик мусора их очищает и превращает в голубое свободное пространство. Потом пользователь вызывает vacuum full, и все это полностью перестраивается, возвращаясь к исходному размеру
Темная область — это старые версии, сборщик мусора их очищает и превращает в голубое свободное пространство. Потом пользователь вызывает vacuum full, и все это полностью перестраивается, возвращаясь к исходному размеру

Раздел, посвященный сборке мусора, важен, потому что зачастую это довольно тяжелый процесс, который может сильно снизить производительность системы. Поэтому нам важно знать, когда он запускался и с какими таблицами работал.

Первый график показывает, какие таблицы подвергались сборке мусора.

Можно увидеть и время, когда происходил вакуум, и его этапы, а также оценить общую длительность
Можно увидеть и время, когда происходил вакуум, и его этапы, а также оценить общую длительность

Есть подробная таблица с временными отсчетами

Временной отсчет, таблица, тип вакуума (ручной или автовакуум, wraparound-автовакуум), длительность на момент отсчета, фаза, прогресс выполнения, включая важное количество циклов очистки индексов, и потребляемая при этом память
Временной отсчет, таблица, тип вакуума (ручной или автовакуум, wraparound-автовакуум), длительность на момент отсчета, фаза, прогресс выполнения, включая важное количество циклов очистки индексов, и потребляемая при этом память

Аналогичные графики и таблицы, только на этот раз отображающие процессы analyze, расположены после вакуума.

Вызовы analyze, детальная информация по отсчетам времени и распределение по типам ожидания
Вызовы analyze, детальная информация по отсчетам времени и распределение по типам ожидания

Секция Command progress. Еще один раздел мы решили создать после многочисленных историй о переживаниях пользователей по поводу длительности выполнения процессов, которые они запускают. Например, пользователь запускает процесс создания нового индекса и ждет… Что происходит? В каком состоянии процесс? Неизвестно. Уже несколько минут длится... Сброшу. И вот на 99% прогресса пользователь терминирует свой запрос. Эх. 

Но теперь это в прошлом: если пользователь запустил какой-то длительный процесс, то в Command Progress он может посмотреть в реальном времени текущий прогресс, этап выполнения и возможных блокировщиков (метрики собраны с представлений pg_stat_progress_create_index, pg_stat_progress_cluster).

Процесс создания индекса на временной панели и в табличном виде по временным отсчетам. Тут можно видеть длительность, этап, прогресс и возможных блокировщиков процесса. Ниже — аналогичные панели для команд Vacuum full/Claster
Процесс создания индекса на временной панели и в табличном виде по временным отсчетам. Тут можно видеть длительность, этап, прогресс и возможных блокировщиков процесса. Ниже — аналогичные панели для команд Vacuum full/Claster

Запросы, таблицы, индексы

Рассмотрим три главные для анализа Performance секции и начнем с запросов.

Секция Queries предназначена для анализа общей утилизации и детальных метрик запросов (метрики собираются с представления pg_stat_statements).

Первым делом — график общей утилизации запросами. Обожаю стекируемые графики: ощущаешь себя геологом, изучающим слои почвы. Внизу видны останки динозавров, еще ниже — лава. 

Каждый цвет — это запрос. Одни запросы выполняются часто и постоянно, такие запросы визуализируются  как слои, толщина которых и определяет утилизацию. Другие запросы, вызываемые редко или вообще разово, выделяются как всплески в этих слоях
Каждый цвет — это запрос. Одни запросы выполняются часто и постоянно, такие запросы визуализируются  как слои, толщина которых и определяет утилизацию. Другие запросы, вызываемые редко или вообще разово, выделяются как всплески в этих слоях

Потребление ресурсов складывается из нагрузки на процессор и систему ввода-вывода. С помощью переменной query_utilization мы можем выбрать другой срез.

Переменная query_utilization
Переменная query_utilization
Просмотр в разрезе IO может вывести совершенно другие запросы в топ
Просмотр в разрезе IO может вывести совершенно другие запросы в топ

Графики — это прекрасно, но у нас есть шикарная таблица, еще более удобный и мощный инструмент для поиска всяких несуразностей в запросах к базе данных. Прежде всего — благодаря возможности сортировки. Например, мы увидели всплеск по временным файлам, горит красный индикатор. Можно кликнуть на соответствующий столбец и вытащить запросы, которые больше всего использовали временные файлы.

Таблица для поиска несуразностей в запросах
Таблица для поиска несуразностей в запросах

В таблице общая утилизация, разбиение на CPU/IO, количество вызовов запроса за выбранный интервал времени, суммарное количество задействованных строк, среднее время выполнения запроса, ну и самые главные, на мой взгляд, метрики, описывающие эффективность доступа к данным, — количество страниц, которые обрабатывал Postgres во время выполнения запроса.

Часть из этих страниц была в кэше, а часть пришлось считать с диска (процент — столбец Hit/Read). Но в любом случае мы призываем разработчиков стремиться по возможности минимизировать общее количество задействованных страниц. Многие недооценивают важность этих значений. 

На мой взгляд, метрики, описывающие количество прочитанных страниц, гораздо больше характеризует качество запроса, чем длительность выполнения, которую часто приводят как показатель его эффективности. Часто можно услышать: «Я оптимизировал запрос, он стал выполняться настолько-то миллисекунд быстрее». Мне кажется продуктивнее другой подход: «Я оптимизировал запрос, и он вместо 1 000 блоков стал собирать 10» — вот это действительно чувствительная оптимизация запроса.

В таблице у нас показаны среднее количество страниц за запрос и количество страниц на одну задействованную строку. Значение Blocks/row становится важным, когда запрос возвращает или модифицирует много строк. Если цена каждой возвращенной строки — 100 прочитанных страниц, то как минимум это должно привлечь внимание, все ли мы делаем оптимально. Если запрос с красными числами — надо что-то делать, если с оранжевыми — желательно тоже, с желтыми — надо обратить внимание. Для oltp-нагрузки (а именно такая преобладает у нас) мы установили такие цветовые thresholds. 

Картинка из нашей документации
Картинка из нашей документации

Запросы бывают разные, и некоторым действительно необходимо прочитать много страниц (например агрегации), но в любом случае мы рекомендуем обращать пристальное внимание на метрики количества задействованных страниц (блоков), особенно для запросов, которые вызываются часто и находятся в топе по утилизации.

Под таблицей расположен еще один график, который как раз показывает количество прочитанных страниц на один запрос. Когда у запроса неожиданно ломается план, это хорошо заметно на этом графике.

На рисунке видно, что запрос 7CE «съел» почти миллион блоков. В таблице среди самых тяжелых запросов его нет, потому что за достаточно большой промежуток времени он внес маленький вклад в общее потребление ресурсов. Но в конкретный момент потребил достаточно много
На рисунке видно, что запрос 7CE «съел» почти миллион блоков. В таблице среди самых тяжелых запросов его нет, потому что за достаточно большой промежуток времени он внес маленький вклад в общее потребление ресурсов. Но в конкретный момент потребил достаточно много

Есть два подхода искать разовые тяжелые запросы потерявшиеся в общей утилизации:

  • Можно на графике выделить более узкий диапазон, в который попадает искомый запрос, и тогда он, скорее всего, выйдет в топ в таблице. 

  • Кликнуть на сортировку и поднять наверх те запросы, которые хуже всего работают с блоками. «Нарушитель», скорее всего, тоже поднимется в топ. 

Видим, что был единственный вызов, который не вернул строк, потребил огромное количество блоков, практически не попал в кэш, всю эту ораву блоков потянул с диска и загрузил их в кэш, вытесняя большое количество полезных горячих страниц
Видим, что был единственный вызов, который не вернул строк, потребил огромное количество блоков, практически не попал в кэш, всю эту ораву блоков потянул с диска и загрузил их в кэш, вытесняя большое количество полезных горячих страниц

В результате остальные запросы наверняка тоже чуть-чуть просели, потому что если они раньше попадали в кеш в 99% случаев, то сейчас стали попадать в 96—98%. Иногда эта разница оказывает весьма существенное влияние. 

Определив проблемный запрос, мы можем кликнуть на него и перейти в отдельный дашборд, который посвящен конкретному запросу, — Query details. 

Доступен текст запроса, его агрегированные временные характеристики и множество графиков, показывающих, как менялось выполнение запроса в динамике
Доступен текст запроса, его агрегированные временные характеристики и множество графиков, показывающих, как менялось выполнение запроса в динамике

На дашборде видим, что количество вызовов и число возвращаемых строк запроса практически не меняется. Но если посмотреть график времени его выполнения, то можно сразу увидеть признаки деградации.

Запрос, который выполнялся за миллисекунды, неожиданно просел до нескольких секунд
Запрос, который выполнялся за миллисекунды, неожиданно просел до нескольких секунд

Еще чуть ниже расположены графики количества считываемых страниц — там мы сразу видим причину подобной деградации.

Резкий рост количества страниц, скорее всего, говорит о неожиданном сломе плана. А за счет того, что часть этих страниц была прочитана с диска (Shared_blks_read), время выполнения просело еще сильнее.
Резкий рост количества страниц, скорее всего, говорит о неожиданном сломе плана. А за счет того, что часть этих страниц была прочитана с диска (Shared_blks_read), время выполнения просело еще сильнее.

Вернемся на дашборд DB Performance.

Секция Tables. Если секции Sessions и Queries представляют некий тактический взгляд на ситуацию с запросами, то секция Tables представляет в большей степени стратегический взгляд. Метрики для этой секции собираются (с представления pg_stat_user_tables) гораздо реже, чем остальные, — раз в час, но это отнюдь не делает их менее полезными. 

Давайте разберем еще один случай слома плана, а заодно подробнее познакомимся с секцией Tables. 

В этот раз слом плана был настолько суровым, что, несмотря на большое количество попыток, запрос не смог завершиться ни разу, падая с ошибкой (ERROR: temporary file size exceeds temp_file_limit). А раз он не завершился ни разу, то и в pg_stat_statements не попал и в queries его не видно.

Но у нас есть еще tables — попробуем найти что-нибудь там.

Ситуация сложилась так: неожиданно, примерно в 02:55, джоб, который до этого выполнялся за вполне вменяемое время, вдруг перестал завершаться. При этом на графиках утилизации видна такая картина:

Резкий рост общей утилизации CPU и IO
Резкий рост общей утилизации CPU и IO
Деградация статистики попадания в кэш. Рост потребления временных файлов
Деградация статистики попадания в кэш. Рост потребления временных файлов

Обращает на себя внимание резко просевший в этот момент коэффициент попадания в кэш и резкий рост количества временных файлов.

Откроем секцию Tables.

Близость к wraparound-катастрофе. График топ-20 самых активных таблиц
Близость к wraparound-катастрофе. График топ-20 самых активных таблиц

Нас интересовал график топ-20 самых активных таблиц.

Виды активности можно менять с помощью переменной table_activity
Виды активности можно менять с помощью переменной table_activity

Например, можно вывести общую статистику, только на чтение (по индексам или последовательно) или только на запись (все виды) и т. д. В данном случае обращает на себя внимание резко возросшее количество считанных последовательным сканированием строк (seq scan)

Под графиком топ-20 у нас есть вот такая шикарная таблица.

Статистики таблиц
Статистики таблиц

Тут самая важная информация с данными на момент окончания выбранного в графане диапазона или агрегированные за этот диапазон значения метрик: размеры таблицы, изменение размеров, оценка по количеству строк, число sec scan, которые были выполнены в этом промежутке времени, плюс количество считанных при этом строк. То же самое по index scan: свежесть статистики, близость к вызову autovacuum, живые и мертвые строки, суммарная инфа по модификационной активности за выбранный период, попадания в кэш и оценка блоатинга. 

Как и в случае с Queries, очень удобно пользоваться сортировкой для вывода в топ таблиц с теми или иными проблемами. По умолчанию строки отсортированы на основании неких очков проблемности, так сказать таблицы для показа таблиц, требующих внимания пользователя.

На первое место у нас попала объемная таблица (0,5 млрд строк) по которой выполнено 289 sec scans (не удивительно, что она попала на первое место в рейтинге проблемности). 

Естественно, такие объемы в основном забирались с диска — близкий к нулю процент попадания в кэш для тушки таблицы. Очевидно, что проблема связана с какими-то запросами к этой таблице. 

В секции Sessions можно найти этот запрос — запрос, который выполнялся нормально, но неожиданно испортился примерно в 02:50. 

select mp1_0.id, ....
from f.payment mp1_0
   left join f.status_history psh1_0 on mp1_0.id=psh1_0.pay_id
where mp1_0.dt_create between $1 and $2
 and mp1_0.state in ($3,$4,$5,$6,$7,$8....)
 and mp1_0.gate_in in ($179)

В нем есть обращение к двум таблицам (master - detail) и проблемная (f.status_history) джойнится к мастеру f.payment. 

Посмотрим, какую дополнительную информацию мы сможем найти для каждой из этих двух таблиц. 

Да-да, есть еще один дашборд, в котором собраны метрики конкретной таблицы и ее индексов. Чтобы открыть его, надо, как обычно, кликнуть на имени проблемной таблицы.

Клик на имени проблемной таблицы
Клик на имени проблемной таблицы

Дашборд Table details сконцентрировал различные визуализации метрик какой-либо таблицы и ее индексов. Здесь очень удобно отслеживать динамику различных характеристик, активностей и обслуживающих таблицу процессов, а также их зависимостей друг от друга (например, соотносить динамику по модификационным изменениям и соответствующим вызовам vacuum/analyze).

Секция Overview собрала общую информацию о таблице и график размера таблицы, индексов и toast.

Общая информация о таблице. График динамики ее размеров
Общая информация о таблице. График динамики ее размеров

Чуть ниже идет секция, в которой собраны метрики по различным видам активности таблицы.

Секция Activity — важнейший график модификационной активности.

Количества вставок новых строк, редактирований и удалений. Также показывается статистика по hot update. Как видим, проблемная таблица status_history — классическая insert-only таблица (нет ни update, ни delete). 
Количества вставок новых строк, редактирований и удалений. Также показывается статистика по hot update. Как видим, проблемная таблица status_history — классическая insert-only таблица (нет ни update, ни delete). 

Графики активности на чтение

Количество индексных и последовательных сканирований, количество прочитанных при этом строк и количество строк на одно сканирование (ввиду обычно разных порядков величин ось для индексного сканирования расположена справа)
Количество индексных и последовательных сканирований, количество прочитанных при этом строк и количество строк на одно сканирование (ввиду обычно разных порядков величин ось для индексного сканирования расположена справа)

У проблемной таблицы обычно преобладают index scan, но в момент сбоя действительно наблюдались тяжелые seq scans (второй график).

Секция Vacuum Analyze Bloat предназначена для отслеживания процессов Vacuum для исследуемой таблицы и оценки его эффективности. Посмотрим, как она работает, на примере недельной партиции одной из таблиц.

Вызовы вакуума и анализа. Длительность процессов вакуума. Количество живых и мертвых кортежей. Возраст самой старой не замороженной строки. Распределение места в таблице. Хорошо видно, как на изначально маленькой партиции вакуум запускается часто и выполняется быстро, но по мере роста таблицы он запускается все реже и выполняется все дольше
Вызовы вакуума и анализа. Длительность процессов вакуума. Количество живых и мертвых кортежей. Возраст самой старой не замороженной строки. Распределение места в таблице. Хорошо видно, как на изначально маленькой партиции вакуум запускается часто и выполняется быстро, но по мере роста таблицы он запускается все реже и выполняется все дольше

Вернемся к проблемной таблице. Видно, что в указанный момент никакой активности по вакууму или analyze не было.

Ни ручных, ни автоматических запусков процессов vacuum/analyze у проблемной таблицы не было
Ни ручных, ни автоматических запусков процессов vacuum/analyze у проблемной таблицы не было

Секция Indexes — еще одна важнейшая для анализа перформанса секция. Тут можно посмотреть полный список индексов таблицы и, самое главное, оценить их эффективность!

Таблица с информацией об индексах с подробным описанием, размерами, приростом и со статистикой их использования (удобно отслеживать неиспользуемые или редко используемые индексы)
Таблица с информацией об индексах с подробным описанием, размерами, приростом и со статистикой их использования (удобно отслеживать неиспользуемые или редко используемые индексы)

В Indexes можно по графикам оценить использование индексов в динамике. Видно, что pk за выбранный диапазон не использовался ни разу, а вот второй индекс (foreign key на головную таблицу), напротив, был активен. 112k сканов, в среднем извлекалось 20 записей за скан. 

Секция Queries. Последняя секция в этом дашборде — полный аналог (library panel) рассмотренной выше секции Queries в дашборде DB Performance за тем исключением, что показываются не все запросы, а только те, в которых так или иначе используется исследуемая таблица.

Очень удобно, обнаружив таблицу с аномалиями в метриках, затрагивающих эффективность доступа к данным, увидеть тут же запросы к ней, потому что с большой вероятностью запрос-виновник как раз и окажется в топе. Зачастую тут же по тексту запроса и списку существующих индексов можно понять, что все проблемы из-за отсутствия индекса по какому-то полю
Очень удобно, обнаружив таблицу с аномалиями в метриках, затрагивающих эффективность доступа к данным, увидеть тут же запросы к ней, потому что с большой вероятностью запрос-виновник как раз и окажется в топе. Зачастую тут же по тексту запроса и списку существующих индексов можно понять, что все проблемы из-за отсутствия индекса по какому-то полю

В нашем случае эта секция нам не поможет, так как проблемные запросы так и не попали в pg_stat_statements. По зависимой таблице ничего выяснить не удалось. Посмотрим теперь на метрики головной таблицы.

Основная информация по головной таблице. Видно большое количество апдейтов, при этом количество hot update = 0
Основная информация по головной таблице. Видно большое количество апдейтов, при этом количество hot update = 0

Мастер-таблица также приличного размера (25 млн строк), но тут уже преобладают апдейты, новых записей вставляется относительно немного. При чтении используются исключительно index scans — все корректно!

Активность по чтению. Исключительно индексный доступ
Активность по чтению. Исключительно индексный доступ

Откроем секцию Vacuum & Analyze.

В пределах этих часов случился один запуск Analyze
В пределах этих часов случился один запуск Analyze

Уже интересно: подозрительно близко к началу сбоя случился analyze таблицы.

Метрики собираются раз в час, и нужна более точная информация. Кликаем на столбик — открываются логи с фильтром на 'analyze' и именем таблицы за выбранный диапазон времени.

Всплывающее окно с линком до деталей analyze
Всплывающее окно с линком до деталей analyze
Лог с точной информацией о запуске Analyze
Лог с точной информацией о запуске Analyze

Аналайз случился прямо перед началом сбоя. Очевидно, он и привел к таким последствиям. Придется подключиться к хосту и внимательно изучить статистику по этой таблице. 

Сам по себе этот кейс оказался достаточно интересным.

Из-за особенностей бизнес-логики, статистического распределения данных и формы запроса (в запросе передавалось в качестве параметров большое количество статусов, которые не попадали в most_common_vals) планировщик неверно оценивал количество возвращаемых из мастер-таблицы строк (2 млн вместо реальных 1—2 записей) и принимал ужасное решение использовать hash join вместо nested loop. 

Естественно, для формирования хэш-таблицы postgres устраивал parallel sec scan для detail-таблицы, который так ни разу и не завершился из-за превышения temp_file_limit. Может быть, мы подробнее расскажем об этом и некоторых других интересных кейсах в отдельной статье.

Секция Partitions. Еще немного о представлении партиционированных таблиц в дашборде Table details. Если в качестве объекта исследования партиционированная таблица, то в дашборде все метрики, все статистики и графики представляют агрегированные значения по всем партициям, что достаточно удобно для оценки общей статистики сразу по всем партициям. 


Значения агрегированы по всем партициям
Значения агрегированы по всем партициям

Но иногда хочется все же посмотреть на общую картину в деталях. Для этого у нас и предназначена секция Partitions. 

В Partition нас ожидает знакомая уже панель (library panel) со статистикой по таблицам. Только на этот раз тут собраны исключительно партиции исследуемой таблицы.

Тут можно обратить внимание на большое количество index scan по прошлым партициям с практически нулевым выхлопом (idx_tup/scan). Это, скорее всего, говорит о том, что разработчики не указывают условия партиционирования в запросах (чаще всего встречается обновление по id. Postgres же не знает, в какой партиции лежит выбранный id, и вынужден сканировать их все). 

Таблица с метриками партиций
Таблица с метриками партиций

Дополнительно ниже можно визуально в динамике оценить активность по всем партициям. Выбор вида активности также управляется переменной activity.

Можно, например, выбрать Write и убедиться, что основная модификационная активность в партиции происходит во время ее диапазона. Но устаревшие партиции все же модифицируются, хотя и не так активно. 

Активность партиций во времени
Активность партиций во времени

Информация об индексах, представленная в Table details, требует еще одного глобального представления — сквозного, так сказать, по всему инстансу. Вернемся на дашборд DB Performance.

Секция Indexes. В этой секции у пользователя есть возможность увидеть информацию обо всех индексах для всех таблиц сразу (метрики собираются с представления pg_stat_user_indexes раз в час).

Агрегированная информация: общий размер, общий блоатинг, попадания в кэш, неиспользуемые индексы (количество, размер, процент), невалидные индексы. Таблица с детальной информацией: размеры, прирост, блоатинг, сканы за все время наблюдения, сканы за выбранный диапазон, извлеченные строки, попадания в кэш, дефинишн индекса
Агрегированная информация: общий размер, общий блоатинг, попадания в кэш, неиспользуемые индексы (количество, размер, процент), невалидные индексы. Таблица с детальной информацией: размеры, прирост, блоатинг, сканы за все время наблюдения, сканы за выбранный диапазон, извлеченные строки, попадания в кэш, дефинишн индекса

С помощью этой секции удобно оценивать использование и проблемы индексов по всему инстансу. Большие индексы, активно растущие, распухшие из-за блоатинга индексы, невалидные, неиспользуемые или редко используемые. Так же, как и в других табличных представлениях, тут удобно пользоваться сортировкой и фильтрацией для отбора топовых в том или ином разрезе индексов.

Заключение

В современных системах управления базами данных мониторинг играет критически важную роль в обеспечении стабильности, производительности и надежности работы. Рассматриваемые дашборды для визуализации собранных метрик представляют собой мощные инструменты, которые позволяют пользователям не только отслеживать текущее состояние системы, но и самостоятельно выявлять и решать проблемы с производительностью без постоянного обращения к администраторам базы данных. Внедренная нами система сбора метрик и созданные на их основе дашборды активно используются нашими командами на протяжении нескольких месяцев. 

Основные выводы по прошествии этого времени:

  1. Дашборды предоставляют пользователям доступ к ключевым метрикам, таким как использование ресурсов (CPU, память, диск), активность запросов, состояние репликаций, прогресс очистки и сбора статистики и т. д. Это позволяет им принимать осознанные решения по оптимизации своих рабочих нагрузок и предотвращению потенциальных проблем.

  2. Визуализация данных помогает своевременно выявлять тренды и аномалии, такие как рост лагов репликации, увеличение времени выполнения запросов или накопление мертвых кортежей. Такой подход позволяет реагировать на проблемы до того, как они станут критическими.

  3. Метрики, связанные с pg_stat_activity, pg_stat_statements, pg_stat_user_tables, pg_stat_progress_vacuum и другими системными представлениями, могут быть сложными для понимания в сыром виде. Дашборды преобразуют эти данные в наглядные графики, диаграммы и сводные таблицы, делая их доступными даже для менее технически подготовленных пользователей.

  4. Когда пользователи могут самостоятельно анализировать производительность и решать типичные проблемы, это снижает нагрузку на администраторов базы данных. Администраторы могут сосредоточиться на более сложных задачах, таких как планирование масштабирования, оптимизация архитектуры и внедрение новых технологий.

  5. Предоставление пользователям инструментов для самостоятельного мониторинга и анализа способствует развитию культуры ответственности за производительность приложений. Это приводит к более тесному взаимодействию между разработчиками, DevOps-инженерами и администраторами баз данных, что в конечном итоге улучшает общую эффективность работы всей организации.

Куда собираемся двигаться дальше?  В этом году мы решили сосредоточится на использовании ИИ для анализа всей собираемой информации. В самом деле, у нас огромное количество метрик, мы знаем, когда БД работает нормально, а когда требуется вмешательство. Ну и еще мы знаем, когда произошел сбой )) 

Выглядит заманчивым и логичным воспользоваться возможностями нейронных сетей и попробовать обучить модель находить проблемные инстансы, определять более подходящие под профиль нагрузки параметры, давать рекомендации по запросам, таблицам и индексам, ну и предсказывать будущие сбои наконец. И у нас появится еще один эффективный помощник — ну, или мы станем его помощниками ))

Теги:
Хабы:
Всего голосов 34: ↑33 и ↓1+35
Комментарии16

Публикации

Информация

Сайт
l.tbank.ru
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия