Статистика
Статистика лежит в основе оценки стоимости в CBO (Cost-Based Optimizer, оптимизатор на основе стоимости) Doris, а её точность напрямую определяет качество плана выполнения запроса. В этой статье рассматриваются способы сбора статистики, команды управления, связанные настройки и методы устранения распространённых неполадок.
Применимые версии: 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, TIMESTAMP_NS, 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;
Сбор часто встречающихся значений
При сборе часто встречающихся значений они сохраняются в статистике столбцов. Эти сведения помогают оптимизатору точнее оценивать предикаты для данных с неравномерным распределением, однако их сбор может потреблять больше памяти для столбцов с высокой кардинальностью.
При ручном полном сборе используйте WITH HOT VALUE, чтобы собрать часто встречающиеся значения:
ANALYZE TABLE lineitem WITH SYNC WITH HOT VALUE;
Не используйте WITH HOT VALUE вместе с WITH SAMPLE: при сборе по выборке часто встречающиеся значения собираются всегда, поэтому указание этой опции вместе с WITH SAMPLE отклоняется. Если WITH HOT VALUE не указан, Doris сохраняет прежнее поведение:
| Способ сбора | Сбор часто встречающихся значений |
|---|---|
| Полный сбор | Отключён |
| Сбор по выборке | Всегда включён |
Автоматический сбор
Назначение: периодически выполнять проверку в фоновом потоке и автоматически поддерживать актуальность статистики.
Переключатель: управляется переменной 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 сканирования для суммирования количества строк в каждом split |
| 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 такие сценарии будут дополнительно оптимизированы.