Learning Platform
Глоссарий Troubleshooting
Урок 09.02 · 22 мин
Средний
cboanalyzeshow-statsconnectors

ANALYZE, SHOW STATS и поставка статистики коннекторами

В прошлом уроке мы выяснили: CBO нужна статистика — row count, NDV, nulls fraction, data size, min/max — и качество планов прямо зависит от её актуальности. Остался практический вопрос: откуда статистика берётся, как её посмотреть и как обновить, когда данные изменились. Этот урок — про три вещи: команду ANALYZE для сбора статистики, команду SHOW STATS для её просмотра, и про то, почему доступность статистики зависит от коннектора.


SHOW STATS: посмотреть, что знает оптимизатор

Начнём с диагностики. SHOW STATS FOR <таблица> показывает статистику, которой CBO располагает по таблице прямо сейчас. Это первое, что смотрят, когда запрос работает медленно: если статистики нет, CBO оптимизирует вслепую.

SHOW STATS FOR tpch.sf1.orders;
  column_name  | data_size | distinct_values_count | nulls_fraction | row_count
---------------+-----------+-----------------------+----------------+-----------
 orderkey      |      NULL |             1500000.0 |            0.0 |      NULL
 custkey       |      NULL |               99996.0 |            0.0 |      NULL
 orderstatus   |  1500000.0|                   3.0 |            0.0 |      NULL
 totalprice    |      NULL |             1462416.0 |            0.0 |      NULL
 orderdate     |      NULL |                2406.0 |            0.0 |      NULL
 NULL          |      NULL |                  NULL |           NULL | 1500000.0

Читается так. Каждая строка — столбец таблицы; последняя строка с NULL в column_name несёт табличную метрику row_count. distinct_values_count — это NDV. У orderstatus NDV равен 3, у orderkey — полтора миллиона (близко к row count, ключ почти уникален) — ровно различие из прошлого урока. data_size для числовых столбцов часто NULL — фиксированную ширину CBO выводит из типа, отдельная метрика не нужна; для orderstatus (строковый) размер указан.

SHOW STATS принимает и запрос, а не только таблицу — тогда покажет оценочную статистику для результата запроса:

SHOW STATS FOR (SELECT * FROM tpch.sf1.orders WHERE orderstatus = 'F');

Это уже не «что хранится», а «что CBO оценил бы» — полезно, чтобы увидеть, как оптимизатор предсказывает селективность предиката.


ANALYZE: собрать статистику

Статистика не появляется сама — её надо собрать. Команда ANALYZE сканирует таблицу и вычисляет метрики:

ANALYZE tpch.sf1.orders;

ANALYZE проходит данные и считает row count, NDV (через HyperLogLog), nulls fraction, data size, min/max — и записывает результат туда, где коннектор хранит статистику. После этого SHOW STATS покажет свежие числа, а CBO будет планировать на их основе.

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

ANALYZE tpch.sf1.orders WITH (columns = ARRAY['orderstatus', 'orderdate']);

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

Цикл работы со статистикой
ANALYZE tableСканирует таблицу, вычисляет row count, NDV, nulls fraction, data size, min/max
статистика записана
SHOW STATS FOR tableПоказывает, какую статистику CBO имеет по таблице сейчас — инструмент диагностики
CBO использует статистику
Планирование запросаCBO оценивает стоимость планов по свежей статистике и выбирает лучший

Когда статистика устаревает

Статистика — снимок состояния данных на момент ANALYZE. Данные меняются — статистика отстаёт. Ключевой вопрос: успевает ли она за изменениями.

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

Данные меняются через Trino. Когда вы делаете INSERT, UPDATE, DELETE, MERGE в таблицу Iceberg, Delta или Hive через сам Trino, движок знает об изменении и может обновлять статистику инкрементально — поддерживать её свежей по ходу записи. В этом случае ручной ANALYZE после каждой записи обычно не требуется: статистика и так не отстаёт.

Данные меняются в обход Trino. Если в таблицу пишет другой инструмент — Spark-джоба, прямая дозапись файлов в S3, внешний загрузчик, — Trino об этом не уведомлён. Статистика, которую он хранит, продолжает описывать старое состояние таблицы. Вот тут ANALYZE обязателен: он единственный способ синхронизировать представление CBO с реальностью. Это и есть основной сценарий ручного ANALYZE — данные изменились мимо Trino.

WARNING
Airflow: запуск ANALYZE как шаг пайплайна

Самый частый источник плохих планов — устаревшая статистика после загрузки данных в обход Trino. Spark-пайплайн дописал в таблицу за ночь сто миллионов строк, а статистика в Trino всё ещё говорит про вчерашний объём. CBO оценивает таблицу как маленькую, выбирает broadcast join, рассылает на каждую ноду сто миллионов строк вместо вчерашней тысячи — и запрос либо ползёт, либо падает по памяти. Правило: после любой массовой загрузки данных в обход Trino запускайте ANALYZE на затронутых таблицах. Сделайте это частью пайплайна загрузки, а не ручной операцией по факту проблемы.


Поставка статистики зависит от коннектора

Теперь принципиальное. Trino — движок без хранилища, и статистику он сам нигде не держит. Статистику поставляет коннектор. CBO спрашивает у коннектора через SPI: «дай мне статистику для этой таблицы», а уж сможет ли коннектор ответить и насколько полно — зависит от коннектора и источника.

Возможны разные уровни поддержки:

Тип источникаКак обычно со статистикой
Iceberg, Delta LakeСтатистика хранится в метаданных формата таблицы; обновляется при DML через Trino; ANALYZE дособирает расширенную статистику
HiveСтатистика — в Hive Metastore; исторически Hive мог не давать data size; ANALYZE собирает метрики в HMS
JDBC (PostgreSQL, MySQL и др.)Коннектор может транслировать запрос к статистике в системные каталоги самой СУБД
Простые коннекторыМогут не отдавать статистику вовсе — тогда CBO работает на эвристиках

Из этого следуют практические выводы. Iceberg и Delta — благодатная для CBO среда: формат таблицы сам несёт метаданные, и статистика во многом поддерживается актуальной. Hive исторически беднее статистикой — отдельные метрики могли быть недоступны, и ANALYZE для Hive-таблиц особенно важен. А если коннектор статистику не отдаёт совсем, никакой ANALYZE не поможет — её просто негде взять и негде хранить, и CBO для такого источника опирается на грубые эвристики.

Статистику отдаёт коннектор, не Trino
CBOОптимизатор запрашивает статистику через SPI — сам он её не хранит
через SPI
КоннекторТранслирует запрос статистики к источнику. Полнота ответа зависит от коннектора и формата
откуда читает
Источник статистикиМетаданные Iceberg/Delta, Hive Metastore, системные каталоги СУБД — или ничего

Что делать, когда статистики нет

Если SHOW STATS показывает NULL там, где ожидались числа, у CBO нет опоры, и план будет так себе. Действия по порядку.

Первое — запустить ANALYZE и проверить SHOW STATS ещё раз. Часто статистики нет просто потому, что её не собирали или данные залили мимо Trino.

Второе — если после ANALYZE статистика всё равно не появилась, проверить, отдаёт ли её коннектор в принципе. Для некоторых источников это ожидаемо: статистики нет и не будет.

Третье — когда статистики получить нельзя, понимать, что CBO деградирует к rule-based эвристикам, и часть решений за него придётся принимать вручную — например, явно задавать тип распределения join’а сессионными свойствами. Эти ручные рычаги — тема следующих уроков модуля; здесь важно зафиксировать: ручное управление нужно ровно тогда, когда автоматике CBO не на что опереться.


Попробуй сам

На песочнице курса (Trino 481):

  1. Выполните SHOW STATS FOR tpch.sf1.customer;. Найдите строку с row_count и столбцы с distinct_values_count. Затем SHOW STATS FOR (SELECT * FROM tpch.sf1.customer WHERE nationkey = 1); — сравните оценочный row_count результата с полным и объясните, как CBO вывел эту оценку.

  2. Рассуждение в двух абзацах. Первый: команда загрузила в Iceberg-таблицу данные через Spark, минуя Trino, и запросы к ней стали медленными. Почему статистика устарела и какая команда это исправит. Второй: почему та же проблема реже возникает, когда данные пишутся в таблицу через сам Trino командами INSERT/MERGE.

  3. Объясните своими словами, почему ANALYZE нельзя считать бесплатной операцией и почему его место — в регламенте обслуживания данных, а не «после каждого запроса». Свяжите ответ с тем, что именно ANALYZE делает с таблицей.


Проверка знанийKnowledge check
Что делают команды ANALYZE и SHOW STATS, когда обязателен ручной ANALYZE, и почему доступность статистики зависит от коннектора?
ОтветAnswer
SHOW STATS FOR таблица показывает статистику, которой CBO располагает по таблице сейчас, — это инструмент диагностики, первое, что смотрят при медленном запросе: каждая строка вывода соответствует столбцу, distinct_values_count — это NDV, отдельная строка несёт табличный row_count. SHOW STATS принимает и запрос — тогда показывает оценочную статистику его результата. ANALYZE собирает статистику: сканирует таблицу, вычисляет row count, NDV через HyperLogLog, nulls fraction, data size, min/max и записывает результат туда, где коннектор хранит статистику; сбор можно сузить до конкретных столбцов через WITH (columns = ...). ANALYZE не бесплатен — это полноценный скан данных, поэтому его место в регламенте обслуживания, а не после каждого запроса. Ручной ANALYZE обязателен, когда данные изменились в обход Trino: если в таблицу пишет Spark-джоба, внешний загрузчик или идёт прямая дозапись файлов, Trino об этом не уведомлён, и его статистика продолжает описывать старое состояние — ANALYZE единственный способ синхронизировать представление CBO с реальностью. Когда же данные меняются через сам Trino командами INSERT/UPDATE/DELETE/MERGE, движок знает об изменении и может обновлять статистику инкрементально, и ручной ANALYZE обычно не нужен. Доступность статистики зависит от коннектора, потому что Trino — движок без хранилища и сам статистику нигде не держит: её поставляет коннектор через SPI. Полнота ответа разная — Iceberg и Delta несут статистику в метаданных формата таблицы, Hive хранит её в Hive Metastore и исторически мог не давать data size, JDBC-коннекторы могут читать системные каталоги СУБД, а простые коннекторы могут не отдавать статистику вовсе, и тогда никакой ANALYZE не поможет — CBO опирается на грубые эвристики.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Что делает команда SHOW STATS FOR table?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6