Этапы исполнения запроса

YQL относится к сильно типизированным (strongly typed) языкам программирования. Это, в частности, означает следующее — перед тем, как YQL запрос начнёт выполняться, он должен быть типизирован (т. е. для каждого узла в графе вычислений должен быть вычислен его тип). При нажатии на кнопку Validate в веб-интерфейсе как раз и происходит типизация.

Например, запрос

SELECT key + 1 AS new_key FROM T;

типизируется следующим образом (тут есть некоторые упрощения):

  1. Загружаются метаданные таблицы T, из которых выясняется, что тип колонки key — Uint32.
  2. Тип литерала всегда известен: тип 1 — Int32.
  3. Вычисляется тип операции + по типам аргументов. Для аргументов Int32,Uint32 результат — Int32.
  4. В результате получается, что тип запроса — список структур с одним Int32 элементом, а именно List<Struct<new_key:Int32>>.

Однако YQL поддерживает и более сложные для типизации случаи, когда тип запроса зависит от значений некоторых выражений, причём эти значения, в свою очередь, могут зависеть от содержимого таблиц. Типичный пример:

$from = "2022-02-01";
$to = SELECT MAX(dt) FROM T1;

INSERT INTO Result
SELECT * FROM RANGE(Dir, $from, $to);

Для того чтобы вывести тип RANGE (т. е. вывести общий тип для таблиц), следует посчитать значение $to.

Другой пример:

$cols = SELECT AGGREGATE_LIST(DISTINCT name) FROM T1 WHERE <condition>; -- динамически формируем интересный нам список колонок

 -- выбираем колонки из списка
SELECT * FROM (SELECT ChooseMembers(TableRow(), $cols) FROM T2) FLATTEN COLUMNS;

Для того чтобы типизировать ChooseMembers, необходимо вычислить значение (не тип) $cols.

Таким образом, можно сделать выводы:

  1. Некоторые запросы на YQL требуют вычислений для типизации.
  2. Иногда эти вычисления требуют чтений из таблиц.

Для типизации подобных запросов в YQL есть отдельная Evaluation стадия, на которой и производятся необходимые вычисления.

Однако у вычислений на этой стадии есть ограничения. Главное из них — суммарный размер таблиц, от которых зависит Evaluation стадия, ограничен. Ограничение по умолчанию составляет 1Мб, но его можно расширить до 10Мб с помощью прагмы yt.EvaluationTableSizeLimit.

Причина таких ограничений — стремление избежать долгой Evaluation стадии, на которой ещё нельзя показать план выполнения запроса и после которой всё ещё возможны пользовательские ошибки типизации. Обидно запустить расчёт на несколько часов, после чего увидеть, что запрос упал с ошибкой 'No such column'.

Единственный способ обойти это ограничение — разбить запрос на два. В первом запросе считается evaluation часть и записывается в таблицу. Второй запрос уже будет зависеть от этой (маленькой по размерам) таблицы.

Предыдущая
Следующая