24.3 новый анализатор запросов включен по умолчанию.
Подробнее о принципах его работы можно прочитать здесь.
Известные несовместимости
Некорректные запросы больше не оптимизируются
Пример 1
number в списке проекций, хотя после агрегации доступно только toString(number).
В старом анализаторе GROUP BY toString(number) оптимизировалось до GROUP BY number,, что делало запрос корректным.
Пример 2
number используется после агрегации с другим ключом.
Прежний анализатор запросов исправлял этот запрос, перемещая фильтр number > 5 из условия HAVING в условие WHERE.
WHERE, чтобы привести его в соответствие со стандартным синтаксисом SQL:
CREATE VIEW с некорректным запросом
VIEW с некорректным запросом SELECT.
В этом случае ошибка возникала при первом SELECT или INSERT (в случае MATERIALIZED VIEW).
Теперь создать VIEW таким способом нельзя.
Пример
Известные несовместимости предложения JOIN
JOIN с использованием столбца из проекции
SELECT нельзя использовать в качестве ключа JOIN USING.
Новая настройка analyzer_compatibility_join_using_top_level_identifier, если она включена, меняет поведение JOIN USING: при разрешении идентификаторов предпочтение отдается выражениям из списка проекций запроса SELECT, а не столбцам из левой таблицы напрямую.
Например:
analyzer_compatibility_join_using_top_level_identifier установлено в true, условие JOIN интерпретируется как t1.a + 1 = t2.b, что соответствует поведению в более ранних версиях.
Результат будет 2, 'two'.
Если эта настройка имеет значение false, по умолчанию используется условие JOIN t1.b = t2.b, и запрос вернёт 2, 'one'.
Если b отсутствует в t1, запрос завершится ошибкой.
Изменения в поведении JOIN USING со столбцами ALIAS/MATERIALIZED
* в запросе JOIN USING со столбцами ALIAS или MATERIALIZED по умолчанию включает эти столбцы в результирующий набор.
Например:
payload вместе с id из обеих таблиц.
В отличие от него, предыдущий анализатор включал эти столбцы ALIAS только при включении определённых настроек (asterisk_include_alias_columns или asterisk_include_materialized_columns),
при этом столбцы могли отображаться в другом порядке.
Чтобы результаты были предсказуемыми и согласованными, особенно при миграции старых запросов на анализатор, рекомендуется явно указывать столбцы в секции SELECT, а не использовать *.
Обработка модификаторов типов столбцов в предложении USING
USING, были унифицированы, чтобы результаты стали более предсказуемыми,
особенно при работе с такими модификаторами типов, как LowCardinality и Nullable.
LowCardinality(T)иT: если столбец типаLowCardinality(T)участвует в JOIN со столбцом типаT, результирующим общим супертипом будетT, то есть модификаторLowCardinalityфактически отбрасывается.Nullable(T)иT: если столбец типаNullable(T)участвует в JOIN со столбцом типаT, результирующим общим супертипом будетNullable(T), что гарантирует сохранение свойства nullable.
id определяется как String, а модификатор LowCardinality из t1 отбрасывается.
Изменения в именах столбцов проекции
Несовместимые типы аргументов функции
if всегда должны иметь общий супертип.
Например, следующий запрос завершается ошибкой There is no supertype for types Array(UInt8), String because some of them are Array and some of them are not:
Неоднородные кластеры
enable_analyzer невозможно.
Мутации обрабатываются предыдущим анализатором
QUALIFY.
Текущий статус можно проверить здесь.
Неподдерживаемые возможности
- Индекс Annoy.
- Индекс Hypothesis. Работа над ним ведется здесь.
- Оконное представление не поддерживается. Его поддержка в будущем не планируется.
Миграция в Cloud
Процесс миграции
- Определите запрос, отфильтровав записи в
system.query_logпоnormalized_query_hash:
- Выполните запрос при включенном анализаторе, добавив следующие настройки.
- Доработайте запрос и проверьте, что его результаты совпадают с выводом при отключённом анализаторе.
Неизвестный идентификатор выражения
Unknown expression identifier ... in scope ... (UNKNOWN_IDENTIFIER). Код исключения: 47
Причина: запросы, зависящие от нестандартного устаревшего поведения, допускающего неоднозначности, — например, обращения к вычисляемым псевдонимам в фильтрах, неоднозначных проекций подзапросов или «динамической» области видимости CTE, — теперь корректно определяются как недопустимые и сразу отклоняются.
Решение: обновите SQL-шаблоны следующим образом:
- Логика фильтрации: перенесите условие из WHERE в HAVING, если фильтрация идёт по результатам, или продублируйте выражение в WHERE, если фильтрация идёт по исходным данным.
- Область видимости подзапроса: явно выберите все столбцы, необходимые внешнему запросу.
- Ключи JOIN: используйте ON с полными выражениями вместо USING, если ключ — это псевдоним.
- Во внешних запросах обращайтесь к псевдониму самого подзапроса/CTE, а не к таблицам внутри него.
Неагрегированные столбцы в GROUP BY
Column ... is not under aggregate function and not in GROUP BY keys (NOT_AN_AGGREGATE). Код исключения: 215
Причина: Старый анализатор позволял выбирать столбцы, которых нет в GROUP BY (часто подставляя произвольное значение). Анализатор следует стандарту SQL: каждый выбранный столбец должен быть либо агрегатом, либо ключом группировки.
Решение: Оберните столбец в any(), argMax() или добавьте его в GROUP BY.
Дублирующиеся имена CTE
CTE with name ... already exists (MULTIPLE_EXPRESSIONS_FOR_ALIAS). Код исключения: 179
Причина: Старый анализатор допускал определение нескольких общих табличных выражений (WITH …) с одним и тем же именем, когда более позднее выражение перекрывало предыдущее. Анализатор не допускает такой неоднозначности.
Решение: Переименуйте повторяющиеся CTE, чтобы их имена были уникальными.
Неоднозначные идентификаторы столбцов
JOIN [JOIN TYPE] ambiguous identifier ... (AMBIGUOUS_IDENTIFIER) Код исключения: 207
Причина: В запросе используется имя столбца, которое присутствует в нескольких таблицах в JOIN, без указания исходной таблицы. Старый анализатор часто определял нужный столбец на основе внутренней логики, тогда как анализатор требует явного указания имени.
Решение: Полностью указывайте столбец в виде table_alias.column_name.
Недопустимое использование FINAL
Table expression modifiers FINAL are not supported for subquery... или Storage ... doesn't support FINAL (UNSUPPORTED_METHOD). Коды исключений: 1, 181
Причина: FINAL — это модификатор хранения таблицы (в частности, для [Shared]ReplacingMergeTree). Анализатор отклоняет FINAL, если он применяется к:
- Подзапросам или производным таблицам (например, FROM (SELECT …) FINAL).
- Движкам таблиц, которые его не поддерживают (например, SharedMergeTree).
Чувствительность функции countDistinct() к регистру
Function with name countdistinct does not exist (UNKNOWN_FUNCTION). Код исключения: 46
Причина: имена функций чувствительны к регистру, либо в анализаторе для них используется строгое сопоставление. countdistinct (полностью в нижнем регистре) больше не распознаётся автоматически.
Решение: используйте стандартную countDistinct (camelCase) или специфичную для ClickHouse функцию uniq.