Статистика
Статистика лежит в основе оценки стоимости в оптимизаторе Doris CBO (Cost-Based Optimizer), и её точность напрямую определяет качество плана выполнения запроса. В статье описаны способы сбора статистики, команды управления, связанные параметры конфигурации и методы устранения типичных неполадок.
Применимые версии: Doris 2.0 и более поздние.
Что нужно знать перед началом
- Вы знаете свою версию Doris (для автоматического сбора требуется версия 2.0.3 или более поздняя).
- Вы определили тип целевого объекта: внутренняя таблица, Hive, Iceberg, Paimon, JDBC и т. д.
- Вы знаете типы целевых столбцов (сбор поддерживается только для базовых типов).
- Вы знаете, нужно ли запускать сбор вручную или использовать автоматический сбор.
Кратко об основных понятиях
Определение в одном предложении: статистика представляет собой метаданные о распределении данных, которые Doris записывает на уровне таблиц и столбцов и которые оптимизатор использует для оценки стоимости и выбора оптимального плана.
Doris собирает статистику по каждому столбцу в пределах таблицы, включая следующие показатели:
| Показатель | Описание |
|---|---|
row_count | Общее количество строк |
data_size | Общий объём данных столбца |
avg_size_byte | Средний объём данных столбца на строку |
ndv | Количество уникальных значений (кардинальность) |
min | Минимальное значение |
max | Максимальное значение |
null_count | Количество значений NULL |
Поддерживаемые типы столбцов: BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, FLOAT, DOUBLE, DATE, DATETIME, STRING, VARCHAR, TEXT.
Не поддерживаются (автоматически пропускаются): JSONB, VARIANT, MAP, STRUCT, ARRAY, HLL, BITMAP, TIME, TIMEV2, VARBINARY.
Результаты сбора хранятся в таблице internal.__internal_schema.column_statistics.
Сбор статистики
В Doris по умолчанию включён автоматический сбор статистики по выборке для внутренних таблиц, поэтому в большинстве случаев вмешательство пользователя не требуется. Для точного контроля используйте сбор вручную.
Сравнение способов сбора
| Критерий | Сбор вручную (ANALYZE) | Автоматический сбор (включён по умолчанию) |
|---|---|---|
| Запуск | По инициативе пользователя | Фоновый поток периодически выполняет проверку |
| Сценарии использования | Срочное обновление, первоначальный сбор, отладка | Регулярное обслуживание, поддержание актуальности |
| Минимальная версия | 2.0 | 2.0.3 |
| Стратегия выборки | Заданное количество или доля строк | По умолчанию выбирается 4194304 строк (2^22) |
| Уровень управления | Таблица / база данных / столбец | Переключатель на уровне кластера + политика на уровне таблицы |
Сбор вручную
Назначение: немедленно запустить сбор и обновление статистики для таблицы или базы данных.
Команда: отправьте задание на сбор вручную с помощью оператора ANALYZE. Подробности см. в справочнике SQL: ANALYZE.
Типичные примеры:
Выполнить полный сбор по всем столбцам таблицы lineitem:
ANALYZE TABLE lineitem;
Выполнить полный сбор по всем столбцам всех таблиц базы данных tpch100:
ANALYZE DATABASE tpch100;
Выполнить сбор по таблице lineitem на выборке из 100000 строк:
ANALYZE TABLE lineitem WITH SAMPLE ROWS 100000;
Выполнить сбор по столбцам l_orderkey и l_linenumber таблицы lineitem на выборке из 100000 строк:
ANALYZE TABLE lineitem (l_orderkey, l_linenumber) WITH SAMPLE ROWS 100000;
Автоматический сбор
Назначение: периодически выполнять проверку в фоновом потоке и автоматически поддерживать актуальность статистики.
Переключатель: управляется переменной ENABLE_AUTO_ANALYZE.
SET GLOBAL ENABLE_AUTO_ANALYZE = TRUE; -- Enable auto collection
SET GLOBAL ENABLE_AUTO_ANALYZE = FALSE; -- Disable auto collection
Механизм работы
После включения фоновый поток периодически проверяет все базы данных и таблицы в InternalCatalog. В каждом цикле проверки решение о повторном сборе принимается по следующим правилам:
- В таблице есть столбцы без статистики.
- Показатель актуальности статистики таблицы ниже порогового значения (по умолчанию 90, задаётся переменной
table_stats_health_threshold). Чем ближе показатель к 100, тем меньше изменились данные; значение ниже 90 означает, что статистика значительно расходится с текущими данными и её необходимо собрать повторно. - Для внутренних таблиц: данные изменились, но за последние 24 часа статистика не собиралась.
Интервал проверки: по умолчанию 5 минут (задаётся параметром auto_check_statistics_in_minutes в fe.conf). Первый цикл начинается через 5 минут после запуска кластера. После завершения каждого цикла поток приостанавливается на 5 минут, а затем начинает следующий цикл.
Продолжительность одного цикла зависит от количества таблиц и объёма данных; сбор статистики для конкретной таблицы в течение 5 минут не гарантируется.
Основные параметры
| Параметр | Назначение | По умолчанию |
|---|---|---|
auto_analyze_table_width_threshold | Максимальное количество столбцов для автоматического сбора | 300 |
huge_table_default_sample_rows | Количество строк в выборке для автоматического сбора | 4194304 (2^22) |
auto_analyze_start_time | Время начала автоматического сбора | 0:00:00 |
auto_analyze_end_time | Время окончания автоматического сбора | 23:59:59 |
Изменить ограничение для широких таблиц (чтобы таблицы с большим количеством столбцов не потребляли слишком много ресурсов):
SET GLOBAL auto_analyze_table_width_threshold = 350;
Выполнять сбор в часы низкой нагрузки (чтобы избежать влияния на рабочие процессы):
SET GLOBAL auto_analyze_start_time = "03:00:00"; -- Start time: 3:00 AM
SET GLOBAL auto_analyze_end_time = "14:00:00"; -- End time: 2:00 PM
Для получения более точных сведений о распределении данных можно увеличить huge_table_default_sample_rows, увеличив тем самым количество строк в выборке.
Сбор статистики внешних таблиц
Типы внешних таблиц: обычно Hive, Iceberg, JDBC, Paimon и т. д.
Матрица возможностей
| Тип внешней таблицы | Полный сбор вручную | Сбор по выборке вручную | Автоматический сбор |
|---|---|---|---|
| Hive | Поддерживается | Поддерживается | Поддерживается |
| Iceberg | Поддерживается | Не поддерживается | Не поддерживается |
| JDBC | Поддерживается | Не поддерживается | Не поддерживается |
| Другие | Не поддерживается | Не поддерживается | Не поддерживается |
Поведение по умолчанию
Внешние объекты Catalog по умолчанию не участвуют в автоматическом сборе статистики по столбцам; собирается только количество строк в таблицах, чтобы избежать избыточного сканирования исторических данных. Чтобы включить автоматический сбор статистики по столбцам:
ALTER CATALOG <catalog_name> SET PROPERTIES ('enable.auto.analyze'='true'); -- Enable
ALTER CATALOG <catalog_name> SET PROPERTIES ('enable.auto.analyze'='false'); -- Disable
Управление на уровне таблицы (имеет приоритет над свойством Catalog):
ALTER TABLE <table_name> SET ("auto_analyze_policy" = "enable"); -- Enable
ALTER TABLE <table_name> SET ("auto_analyze_policy" = "disable"); -- Disable
ALTER TABLE <table_name> SET ("auto_analyze_policy" = "base_on_catalog"); -- Follow the catalog
Для внешних таблиц показатель актуальности не используется. После включения автоматического сбора статистика внешней таблицы по умолчанию собирается не чаще одного раза в 24 часа. Минимальный интервал можно изменить с помощью external_table_auto_analyze_interval_in_millis.
Стратегия оценки количества строк
| Тип внешней таблицы | Метод оценки |
|---|---|
| Hive | Сначала берётся numRows из Parameters; если значение отсутствует, для оценки используются totalSize и схема; если и этих данных нет, оценка выполняется по размеру файлов |
| Iceberg | Вызов API снимков для получения total-records и total-position-deletes, используемых в расчёте |
| Paimon | Вызов API сканирования для суммирования количества строк в каждом фрагменте |
| JDBC | Получение с помощью команды определения количества строк в подключённой базе данных (поддерживаются MySQL, Oracle, PostgreSQL, SQLServer) |
| Другие | Автоматическое получение и оценка пока не поддерживаются |
Если получение размеров файлов потребляет слишком много ресурсов, можно отключить оценку по размеру файлов для Hive:
SET GLOBAL enable_get_row_count_from_file_list = FALSE;
Просмотреть оценочное количество строк во внешней таблице:
SHOW TABLE STATS table_name;
Если row_count показывает -1, количество строк не удалось получить либо таблица пуста.
Управление заданиями сбора статистики
Просмотр заданий сбора статистики
Назначение: просмотр отправленных асинхронных заданий сбора статистики (история синхронных заданий не сохраняется).
Команда:
SHOW ANALYZE [job_id];
Подробности см. в разделе SHOW ANALYZE.
Примечание: система хранит историю только 20000 заданий. Значения столбцов вывода:
| Столбец | Описание |
|---|---|
job_id | Идентификатор задания сбора статистики |
catalog_name | Имя Catalog |
db_name | Имя базы данных |
tbl_name | Имя таблицы |
col_name | Список имён столбцов (index_name:column_name) |
job_type | Тип задания |
analysis_type | Тип статистики |
message | Сообщение задания |
state | Состояние задания |
progress | Ход выполнения задания |
schedule_type | Тип планирования |
start_time | Время начала задания |
end_time | Время окончания задания |
Пример:
mysql> SHOW ANALYZE 245073\G
*************************** 1. row ***************************
job_id: 93021
catalog_name: internal
db_name: tpch
tbl_name: region
col_name: [region:r_regionkey,region:r_comment,region:r_name]
job_type: MANUAL
analysis_type: FUNDAMENTALS
message:
state: FINISHED
progress: 3 Finished | 0 Failed | 0 In Progress | 3 Total
schedule_type: ONCE
start_time: 2024-07-11 15:15:00
end_time: 2024-07-11 15:15:33
Просмотр задач сбора статистики
Назначение: каждое задание может содержать несколько задач, каждая из которых соответствует одному столбцу. Можно просмотреть ход выполнения на уровне задач.
Команда:
SHOW ANALYZE TASK STATUS [job_id];
Пример:
mysql> SHOW ANALYZE TASK STATUS 93021;
+---------+-------------+------------+---------+------------------------+-----------------+----------+
| task_id | col_name | index_name | message | last_state_change_time | time_cost_in_ms | state |
+---------+-------------+------------+---------+------------------------+-----------------+----------+
| 93022 | r_regionkey | region | | 2024-07-11 15:15:33 | 32883 | FINISHED |
| 93023 | r_comment | region | | 2024-07-11 15:15:33 | 32883 | FINISHED |
| 93024 | r_name | region | | 2024-07-11 15:15:33 | 32883 | FINISHED |
+---------+-------------+------------+---------+------------------------+-----------------+----------+
Просмотр статистики столбцов
Назначение: просмотр собранной статистики на уровне столбцов.
Команда:
SHOW COLUMN [cached] STATS table_name [ (column_name [, ...]) ];
Параметры:
| Параметр | Описание |
|---|---|
cached | Показать только статистику из кеша в памяти FE |
table_name | Целевая таблица; можно указать в виде db_name.table_name |
column_name | Целевой столбец (можно указать несколько столбцов через запятую); если не указан, выводятся все столбцы |
Пример:
mysql> SHOW COLUMN STATS region (r_regionkey)\G
*************************** 1. row ***************************
column_name: r_regionkey
index_name: region
count: 5.0
ndv: 5.0
num_null: 0.0
data_size: 20.0
avg_size_byte: 4.0
min: 0
max: 4
method: FULL
type: FUNDAMENTALS
trigger: MANUAL
query_times: 0
updated_time: 2024-07-11 15:15:33
1 row in set (0.36 sec)
Просмотр сводки статистики таблицы
Назначение: просмотр сводных сведений о сборе статистики на уровне таблицы.
Команда:
SHOW TABLE STATS table_name;
table_name можно указать в виде db_name.table_name.
Столбцы вывода:
| Столбец | Описание |
|---|---|
updated_rows | Количество строк таблицы, обновлённых после последнего ANALYZE |
query_times | Зарезервированный столбец для учёта количества запросов в будущих версиях |
row_count | Количество строк в таблице (может не соответствовать точному количеству строк на момент выполнения команды) |
updated_time | Время последнего обновления статистики |
columns | Столбцы, для которых собрана статистика |
trigger | Способ запуска сбора статистики |
new_partition | Есть ли новая партиция, в которую впервые загружены данные |
user_inject | Введена ли статистика пользователем вручную |
Прекращение заданий сбора статистики
Назначение: прекращение выполняющегося асинхронного задания сбора статистики.
Команда:
KILL ANALYZE job_id;
job_id представляет собой значение, возвращаемое при асинхронном выполнении ANALYZE; его также можно получить с помощью SHOW ANALYZE.
Пример: прекратить задание сбора статистики с идентификатором 52357.
mysql> KILL ANALYZE 52357;
Удаление статистики
Назначение: ручная очистка статистики существующей таблицы. Статистика удалённых объектов периодически очищается в фоновом режиме и не требует действий пользователя.
Команда:
DROP STATS table_name;
Переменные сеанса и параметры конфигурации
Переменные сеанса
| Переменная сеанса | Описание | По умолчанию |
|---|---|---|
auto_analyze_start_time | Время начала автоматического сбора | 0:00:00 |
auto_analyze_end_time | Время окончания автоматического сбора | 23:59:59 |
enable_auto_analyze | Включён ли автоматический сбор | TRUE |
huge_table_default_sample_rows | Количество строк в выборке для больших таблиц | 4194304 |
table_stats_health_threshold | Диапазон 0-100; статистика считается устаревшей при изменении (100 - порог)% данных | 90 |
auto_analyze_table_width_threshold | Максимальное количество столбцов для автоматического сбора; таблицы с большим количеством столбцов исключаются | 300 |
enable_get_row_count_from_file_list | Оценивать ли количество строк в таблицах Hive по размеру файлов | TRUE (до 2.1.5 по умолчанию FALSE) |
Параметры конфигурации FE
Следующие параметры конфигурации FE обычно не требуют особого внимания.
| Параметр конфигурации FE | Описание | По умолчанию |
|---|---|---|
analyze_record_limit | Определяет количество сохраняемых записей о выполнении заданий сбора статистики | 20000 |
stats_cache_size | Количество записей в кеше статистики на стороне FE | 500000 |
statistics_simultaneously_running_task_num | Количество асинхронных заданий сбора статистики, которые могут выполняться одновременно | 3 |
statistics_sql_mem_limit_in_bytes | Объём памяти BE, доступный каждому SQL-запросу сбора статистики | 2L * 1024 * 1024 (2 GiB) |
Часто задаваемые вопросы (FAQ)
Вопрос 1: Как проверить, собрана ли статистика по таблице?
Шаг 1: проверьте наличие результатов сбора.
SHOW COLUMN STATS table_name;
Шаг 2: проверьте, загружена ли статистика в кеш FE.
SHOW COLUMN CACHED STATS table_name;
Если оба результата пусты, у таблицы сейчас нет статистики. Пример вывода при наличии собранной статистики:
mysql> SHOW COLUMN CACHED STATS mvTestDup;
+-------------+------------+-------+------+----------+-----------+---------------+------+------+--------+--------------+---------+-------------+---------------------+
| column_name | index_name | count | ndv | num_null | data_size | avg_size_byte | min | max | method | type | trigger | query_times | updated_time |
+-------------+------------+-------+------+----------+-----------+---------------+------+------+--------+--------------+---------+-------------+---------------------+
| key1 | mvTestDup | 6.0 | 4.0 | 0.0 | 48.0 | 8.0 | 1 | 1001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| key2 | mvTestDup | 6.0 | 4.0 | 0.0 | 48.0 | 8.0 | 2 | 2001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| value2 | mvTestDup | 6.0 | 4.0 | 0.0 | 24.0 | 4.0 | 4 | 4001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| value1 | mvTestDup | 6.0 | 4.0 | 0.0 | 24.0 | 4.0 | 3 | 3001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| mv_key1 | mv1 | 6.0 | 4.0 | 0.0 | 48.0 | 8.0 | 1 | 1001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
| value3 | mvTestDup | 6.0 | 4.0 | 0.0 | 24.0 | 4.0 | 5 | 5001 | FULL | FUNDAMENTALS | MANUAL | 0 | 2024-07-22 10:53:25 |
+-------------+------------+-------+------+----------+-----------+---------------+------+------+--------+--------------+---------+-------------+---------------------+
6 rows in set (0.00 sec)
Шаг 3: проверьте точность, выполнив SQL вручную.
SELECT count(1), ndv(col1), min(col1), max(col1) FROM table;
Если различие между count и ndv не превышает одного порядка величины, точность считается приемлемой.
Вопрос 2: Почему статистика по таблице никогда не собирается автоматически?
Проверка 1: включён ли автоматический сбор.
SHOW VARIABLES LIKE "enable_auto_analyze";
-- If false, enable it:
SET GLOBAL enable_auto_analyze = TRUE;
Проверка 2: не превышает ли количество столбцов в таблице значение auto_analyze_table_width_threshold (по умолчанию 300). Таблицы, превышающие этот предел, исключаются из автоматического сбора.
SHOW VARIABLES LIKE "auto_analyze_table_width_threshold";
-- If smaller than the table width, adjust:
SET GLOBAL auto_analyze_table_width_threshold = 350;
Проверка 3: выполняются ли другие задания.
SHOW AUTO ANALYZE;
Автоматический сбор выполняется последовательно в одном потоке и обходит все базы данных и таблицы, поэтому полный цикл обхода может занимать много времени.
Вопрос 3: Почему для некоторых столбцов нет статистики?
Сбор статистики поддерживается только для столбцов базовых типов. Сложные типы (например, JSONB, VARIANT, MAP, STRUCT, ARRAY, HLL, BITMAP, TIME, TIMEV2, VARBINARY) автоматически пропускаются.
Вопрос 4: Ошибка Stats table not available, please make sure your cluster status is normal
Обычно это означает, что внутренняя таблица статистики находится в неисправном состоянии. Порядок диагностики:
Шаг 1: проверьте, все ли BE работают нормально.
Шаг 2: получите все tabletId таблицы статистики.
SHOW TABLETS FROM internal.__internal_schema.column_statistics;
Шаг 3: выполните диагностику каждого tablet по очереди.
ADMIN DIAGNOSE TABLET tablet_id;
Шаг 4: после устранения проблем с tablet повторно соберите статистику.
Вопрос 5: Что делать, если статистика собирается недостаточно своевременно?
- Если обновление требуется срочно: выполните
ANALYZEдля целевой таблицы вручную. - Измените порог актуальности: значение по умолчанию
table_stats_health_threshold = 90означает, что сбор запускается только при изменении более 10% данных. Можно повысить его до 95 (тогда сбор будет запускаться при изменении более 5% данных):
SET GLOBAL table_stats_health_threshold = 95;
Вопрос 6: Что делать, если автоматический сбор потребляет слишком много ресурсов?
Автоматический сбор использует выборку и выполняется последовательно в одном потоке, поэтому потребление ресурсов обычно можно контролировать. Однако в следующих случаях расход памяти может быть повышенным:
- Таблицы с большим количеством партиций.
- Таблицы с очень крупными отдельными tablet.
Рекомендации по оптимизации:
- При создании таблицы разумно планируйте количество tablet и не допускайте чрезмерного размера отдельных tablet.
- Включайте автоматический сбор в часы низкой нагрузки на систему (см.
auto_analyze_start_time/auto_analyze_end_time). - Для больших таблиц выполняйте сбор вручную в часы низкой нагрузки.
- В линейке Doris 3.x такие сценарии будут дополнительно оптимизированы.