Metricdb
metricdb - это база данных PostgreSQL, предназначенная для хранения и анализа метрик мониторинга запросов.
В metricdb хранятся данные, полученные из агента (greenplum.metric.agent). Подробнее об агенте см. на странице greenplum.metric.agent.
Структура базы данных определяется DDL-скриптами, распооложенными в папке postgres_migration модуля агента (greenplum.metric.agent).
Подключение и работа
Для удобства работы с metricdb необходимо создать подключение через DBeaver.
Как правило, база данных metricdb находится на мониторинговом хосте.

Рекомендации и ограничения по использованию
- Не допускается ручное создание объектов в приведённых схемах
- Не допускается ручная модификация информации в схеме greenplum_metric_migration
- Не рекомендуется делать запросы ко всему объему данных. Рекомендуется накладывать ограничения по полю партицирования (обычно используется
created_date) - Установить следующие параметры сессии для работы с партициями:
sql
set enable_partitionwise_join=on;
set enable_partitionwise_aggregate=on;
База данных metricdb содержкит следующие схемы:
- greenplum_metric - содержит информацию по запросам базы Greenplum
- greenplum_metric_migration - служебная схема с информацией по эволюции схемы greenplum_metric
- greenplum_resmodel - схема для хранения настроек ресурсных групп
- greenplum_metadata - содержит копию метаданных из наблюдаемой Greenplum
Описание таблиц metricdb
В схеме greenplum_metric располагаются следующие объекты:
Таблицы с информацией по запросам
- query - содержит общую информацию по запросам
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| query_id | serial4 | Да | Идентификатор запроса |
| plan_generator_id | int4 | Да | Идентификатор оптимизатора плана. Справочник: plan_generator_type |
| query_text | text | Да | Текст запроса |
| ccnt | int4 | Да | Номер запроса в сессии |
| ssid | int4 | Да | Идентификатор сессии |
| tmid | int4 | Да | Время старта сервера |
| username | text | Да | Имя пользователя |
| databasename | text | Да | Имя базы данных |
| applicationname | text | Да | Название клиентского приложения |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- uery_log - содержит информацию по изменению статуса запросов
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| query_log_id | bigserial | Да | Идентификатор записи |
| query_id | int4 | Да | Идентификатор запроса |
| query_status_id | int4 | Да | Идентификатор статуса запроса. Справочник: query_status_type |
| segment_id | int4 | Да | Идентификатор сегмента. Справочник: segment |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- query_metric - содержит общие метрики запроса (утилизация ресурсов)
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| query_metric_id | bigserial | Да | Идентификатор записи |
| query_id | int4 | Да | Идентификатор запроса |
| metric_stage_id | int4 | Да | Идентификатор стадии выполнения запроса. Справочник: metric_stage_type |
| segment_id | int4 | Да | Идентификатор сегмента. Справочник: segment |
| pid | int4 | Да | Идентификатор процесса в ОС |
| gp_role | int2 | Да | Режим работы процесса базы данных ● dispatch - режим координатора (узел мастер) ● execute - режим работы экзекьютора ● utility - режим обслуживания экземпляра БД postgres Может меняться в рамках подключения |
| gp_session_role | int2 | Да | Режим работы процесса базы данных ● dispatch - режим координатора (узел мастер) ● execute - режим работы экзекьютора ● utility - режим обслуживания экземпляра БД postgres Задается при старте кластера |
| resource_group | text | Да | Имя ресурсной группы в которой выполнялся запрос |
| cpu_runningtime | float8 | Да | Время от момента старта процесса (pid) |
| cpu_usertime | float8 | Да | Время работы процесса (pid) в пользовательском пространстве |
| cpu_kerneltime | float8 | Да | Время работы процесса (pid) в пространстве ядра |
| mem_size | int8 | Да | Зарезервированная процессом (pid) память в байтах |
| mem_peak_kb | int4 | Да | Максимальный размер зарезервированный процессом (pid) памяти в килобайтах |
| storage_rchar | int8 | Да | Количество байт которые процесс запросил для чтения |
| storage_wchar | int8 | Да | Количество байт которые процесс запросил для записи |
| storage_syscr | int8 | Да | Количество вызовов методов чтения |
| storage_syscw | int8 | Да | Количество вызовов методов записи |
| storage_read_bytes | int8 | Да | Объем прочитанных данных с диска |
| storage_write_bytes | int8 | Да | Объем записанных на диск данных |
| storage_cancelled_write_bytes | int8 | Да | Объем отмененных байтов на запись |
| slice_id | int4 | Да | Идентификатор этапа выполнения запроса |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- query_param - дополнительные параметры с которыми был запущен запрос (сбор ограничен настройкой хуков)
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| query_param_id | bigserial | Да | Идентификатор записи |
| query_id | int4 | Да | Идентификатор запроса |
| param_key_id | int4 | Да | Идентификатор параметра сессии. Справочник: param_key_type |
| param_value | text | Да | Значение параметра |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
- query_plan_text - содержит выполненный план запроса
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| query_id | serial4 | Да | Идентификатор запроса |
| plan_text | text | Да | План выполнения запроса |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- query_plan_text_preview - содержит предварительный план запроса
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| query_id | serial4 | Да | Идентификатор запроса |
| plan_text | text | Да | План выполнения запроса |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
Таблицы с информацией по узлам дерева запросов
- plan_node - содержит информацию по узлам дерева запросов
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| plan_node_id | bigserial | Да | Идентификатор записи |
| query_id | int4 | Да | Идентификатор запроса |
| parent_plan_node_id | int8 | Да | Идентификатор родительского узла |
| plan_node_type_id | int4 | Да | Идентификатор типа узла. Справочник: plan_node_type |
| plan_node_num | int4 | Да | Порядковый номер узла в рамках запроса |
| optional_arg_1 | int4 | Да | Дополнительные параметры для внутреннего использования |
| optional_arg_2 | int4 | Да | Дополнительные параметры для внутреннего использования |
| startup_cost | float8 | Да | Стоимость до получения первого результата |
| total_cost | float8 | Да | Общая стоимость |
| plan_rows | float8 | Да | Предполагаемое количество строк |
| plan_width | int4 | Да | Предполагаемый средний объем строки |
| motion_type | int2 | Да | Тип перераспределения данных |
| motion_broadcast | bool | Да | Флаг перераспределения данных типом broadcast |
| motion_locustype | int2 | Да | Тип доступности данных на узлах кластера при выполнении запроса |
| motion_parent_sliceid | int4 | Да | Идентификатор родительского этапа выполнения запроса |
| relation_oid | int4 | Да | Внутренний идентификатор объекта базы данных Greenplum |
| relation_schema | text | Да | Имя схемы базы данных Greenplum |
| relation_name | text | Да | Имя объекта базы данных Greenplum |
| relation_dynamic_scanid | int4 | Да | Идентификатор операции чтения партицированной таблицы |
| scan_index_name | text | Да | Используемый при чтении индекс |
| scan_direction | int2 | Да | Направление чтения при считывании |
| slice_id | int4 | Да | Идентификатор этапа выполнения запроса |
| slice_segments | int4 | Да | Количество сегментов участвующих в текущем этапе |
| slice_gang_type | int2 | Да | Тип набора процессов работающих над одним этапом плана в рамках сегмента |
| slice_gang | int4 | Да | Идентификатор процессов работающих над одним этапом плана в рамках сегмента |
| node_statement | jsonb | Да | Детали выполнения узла запроса |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- plan_node_log - содержит информацию по изменению статусов узла дерева запросов
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| plan_node_log_id | bigserial | Да | Идентификатор записи |
| plan_node_id | int8 | Да | Идентификатор узла запроса |
| plan_node_stage_id | int4 | Да | Идентификатор плана узла запроса. Справочник: plan_node_stage_type |
| segment_id | int4 | Да | Идентификатор сегмента. Справочник: segment |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- plan_node_metric - содержит информацию по метрикам узла дерева запросов
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| plan_node_metric_id | bigserial | Да | Идентификатор записи |
| plan_node_id | int8 | Да | Идентификатор узла запроса |
| metric_stage_id | int4 | Да | Идентификатор стадии выполнения запроса. Справочник: metric_stage_type |
| segment_id | int4 | Да | Идентификатор сегмента. Справочник: segment |
| pid | int4 | Да | Идентификатор процесса в ОС |
| gp_role | int2 | Да | Режим работы процесса базы данных ● dispatch - режим координатора (узел мастер) ● execute - режим работы экзекьютора ● utility - режим обслуживания экземпляра БД postgres Может меняться в рамках подключения |
| gp_session_role | int2 | Да | Режим работы процесса базы данных ● dispatch - режим координатора (узел мастер) ● execute - режим работы экзекьютора ● utility - режим обслуживания экземпляра БД postgres Задается при старте кластера |
| resource_group | text | Да | Имя ресурсной группы в которой выполнялся запрос |
| cpu_runningtime | float8 | Да | Время от момента старта процесса (pid) |
| cpu_usertime | float8 | Да | Время работы процесса (pid) в пользовательском пространстве |
| cpu_kerneltime | float8 | Да | Время работы процесса (pid) в пространстве ядра |
| mem_size | int8 | Да | Зарезервированная процессом (pid) память в байтах |
| mem_peak_kb | int4 | Да | Максимальный размер зарезервированный процессом (pid) памяти в килобайтах |
| storage_rchar | int8 | Да | Количество байт которые процесс запросил для чтения |
| storage_wchar | int8 | Да | Количество байт которые процесс запросил для записи |
| storage_syscr | int8 | Да | Количество вызовов методов чтения |
| storage_syscw | int8 | Да | Количество вызовов методов записи |
| storage_read_bytes | int8 | Да | Объем прочитанных данных с диска |
| storage_write_bytes | int8 | Да | Объем записанных на диск данных |
| storage_cancelled_write_bytes | int8 | Да | Объем отмененных байтов на запись |
| spill_file_count | int4 | Да | Количество временных файлов |
| spill_total_size | int8 | Да | Объем временных файлов на диске |
| slice_id | int4 | Да | Идентификатор этапа выполнения запроса |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
- act_plan_node_metric - содержит информацию о количестве обработанных строк узлом дерева запроса
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| act_plan_node_metric_id | bigserial | Да | Идентификатор записи |
| plan_node_id | int8 | Да | Идентификатор узла запроса |
| segment_id | int4 | Да | Идентификатор сегмента. Справочник: segment |
| ntuples | int8 | Да | Количество считанных кортежей |
| firsttuple | float8 | Да | Время доступа к первой строке |
| tuplecount | int8 | Да | Число строк в текущем цикле |
| nloops | int8 | Да | Количество повторных считываний |
| total | float8 | Да | Общее время вывода данных |
| startup | float8 | Да | Затраченное время до вывода данных |
| created_at | timestamp | Да | Дата возникновения события на сервере |
| processed_at | timestamp | Да | Дата обработки на агенте и сохранения |
| created_date | date | Да | Дата от created_at таблицы query. Поле партицирования таблицы |
Справочники
- metric_stage_type - справочник стадий выполнения запросов
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| metric_stage_id | serial4 | Да | Идентификатор |
| code | int4 | Да | Код |
| name | text | Да | Имя |
- param_key_type - справочник параметров запросов собираемых хуком
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| param_key_id | serial4 | Да | Идентификатор |
| name | text | Да | Имя |
- plan_generator_type - справочник оптимизаторов кластера Greenplum
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| plan_generator_id | serial4 | Да | Идентификатор |
| code | int4 | Да | Код |
| name | text | Да | Имя |
- plan_node_type - справочник типов узлов дерева запросов
| Столбец | Тип данных | Обязательность | Описание |
|---|---|---|---|
| plan_node_type_id | serial4 | Да | Идентификатор |
| code | int4 | Да | Код |
| name | text | Да | Имя |
Примеры полезных запросов к metricdb
Ниже представлены примеры получения полезных показателей по запросам из статистике в базе metricdb:
- Флаг сбора статистики (stat_missing_flg)
- Наличие спилл файлов (spill_file_count, spill_total_size)
- Индекс дистрибьюции (distribution_index)
- Наличие перекосов данных (skew_index)
- Индекс неточности статистики (expectation_index)
- Количество прочитанных запросом строк (read_lines)
- Индекс перераспределения данных (broadcast_index)
Запрос на индекс перекосов
select
a.query_id,
a.query_text,
a.created_date,
max(a.skew_rows) * 100::double precision as skew_volume
from
(
select
pn.query_id,
q.query_text,
pn.plan_node_id,
apnm.ntuples,
apnm.nloops,
q.created_date,
(max(apnm.ntuples / apnm.nloops) over (partition by pn.query_id,
pn.plan_node_id) - min(
case
when apnm.ntuples = 0 then null::bigint
else apnm.ntuples / apnm.nloops::double precision
end) over (partition by pn.query_id,
pn.plan_node_id))::double precision / max(
case
when apnm.ntuples = 0 then 1::bigint
else apnm.ntuples / apnm.nloops::double precision
end) over (partition by pn.query_id,
pn.plan_node_id)::double precision as skew_rows
from greenplum_metric.query q
join greenplum_metric.plan_node pn on
pn.query_id = q.query_id
and pn.created_date = q.created_date
join greenplum_metric.act_plan_node_metric apnm on
pn.plan_node_id = apnm.plan_node_id
and pn.created_date = apnm.created_date
join greenplum_metric.plan_node_type pnt on
pn.plan_node_type_id = pnt.plan_node_type_id
where
pnt.name != 'Result'
and q.created_date in ('2023-11-01', '2023-11-02', '2023-11-03')
group by
1,2,3,4,5,6) a
group by
1,2,3
order by
skew_volume desc
limit 4; --топ 4 запросов с перекосами за 23.03.2023
### Запрос на кол-во прочитанных строк
select
q.created_date,
pn.query_id,
q.query_text,
pn.relation_schema,
pn.relation_name,
sum(case when s.seg_index >= 0 then apnm.ntuples / apnm.nloops else 0 end) read_lines
from
greenplum_metric.plan_node pn,
greenplum_metric.plan_node_type pnt,
greenplum_metric.act_plan_node_metric apnm,
greenplum_metric.segment s,
greenplum_metric.query q
where
pn.plan_node_type_id = pnt.plan_node_type_id
and pn.plan_node_id = apnm.plan_node_id
and q.query_id = pn.query_id
and pn.relation_name != ''
and apnm.segment_id = s.segment_id
and q.created_date >= '2023-11-01'
and q.created_date < '2023-11-03'
group by
1,2,3,4,5
order by
query_id;
--Запрос на кол-во прочитанных запросами строк
Запрос на флаг сбора статистики
select
a.query_id,
a.query_text,
a."name",
a.plan_rows,
stat_missing_flg
from
(
select
pn.query_id,
q.query_text,
pnt."name",
pn.plan_rows,
q.created_date,
case
when pnt.name = 'SeqScan'::text
and pn.plan_rows = 1::double precision
then 1
else 0
end as stat_missing_flg
from
greenplum_metric.plan_node pn
join greenplum_metric.query q on
pn.query_id = q.query_id
join greenplum_metric.plan_node_type pnt on
pn.plan_node_type_id = pnt.plan_node_type_id
where
q.created_date >= '2023-11-01'
and q.created_date < '2023-11-04'
group by
1,2,3,4,5
order by
query_id) as a
where
stat_missing_flg > 0;
--не собрана статистика, либо в считываемой(ых) таблице(ах) одна строка
Запрос на отношение план/факт по количеству строк
select
a.query_id,
a.query_text,
a.created_date,
max(a.row_expectation) as expectation_index
from
(
select
pn.query_id,
q.query_text,
pn.plan_rows,
pn.plan_node_id,
q.created_date,
sum(case
when pn.plan_rows = 0::double precision then 1::double precision
else pn.plan_rows
end) over (partition by pn.query_id,
pn.plan_node_id) as row_expectation
from
greenplum_metric.plan_node pn
join greenplum_metric.query q on
pn.query_id =
q.query_id
where
q.created_date >= '2023-11-01'
and q.created_date < '2023-11-04'
group by
1,2,3,4,5
order by
query_id) a
group by
1,2,3
order by
query_id;
--планировщик считает, что строк в таблице меньше, чем по факту
Запрос на индекс дистрибьюции
select
pn.query_id,
q.query_text,
q.created_date,
sum(
case
when pnt.name = 'Motion'::text and pn.motion_type = 0
then pn.plan_rows * pn.plan_width::double precision
else 0::double precision
end) as distribution_index
from
greenplum_metric.plan_node pn
join greenplum_metric.plan_node_type pnt on
pn.plan_node_type_id = pnt.plan_node_type_id
join greenplum_metric.query q on
pn.query_id = q.query_id
where
q.created_date >= '2023-11-01'
and q.created_date < '2023-11-04'
group by
1,2,3
order by
query_id;
Запрос на индекс распределения данных
select
q.query_id :: int4,
q.username :: text,
q.query_text :: text,
q.created_date :: date,
q_toxic.broadcast_index :: float8
from
greenplum_metric.query q
left join (
select
query_id,
sum(broadcast_volume) as broadcast_index
from
(
select
pn.query_id ,
case
when pnt."name" = 'Motion'
and pn.motion_broadcast = true
then (pn.plan_rows * pn.plan_width)
else 0
end as broadcast_volume
from
greenplum_metric.query q
join greenplum_metric.plan_node pn on
q.query_id = pn.query_id
and q.created_date = pn.created_date
join greenplum_metric.plan_node_type pnt on
pn.plan_node_type_id = pnt.plan_node_type_id
where
q.created_date in ('2023-11-01', '2023-11-02', '2023-11-03')
) t
group by
t.query_id
) q_toxic on
q_toxic.query_id = q.query_id
where
q.created_date in ('2023-11-01', '2023-11-02', '2023-11-03');