Skip to main content
En la versión 24.3 de ClickHouse, el analizador de consultas estaba habilitado de forma predeterminada. Puede obtener más información sobre su funcionamiento aquí. Desde la versión 26.9, el analizador es obligatorio: el ajuste enable_analyzer está obsoleto, se rechaza cualquier intento de establecerlo en 0 y ya no se admite el análisis de consultas que ClickHouse utilizaba antes de la 24.3. Las incompatibilidades que se enumeran a continuación describen en qué se diferenciaba aquel análisis anterior, de modo que pueda actualizarse una consulta escrita para él; para observar su comportamiento, ejecute la consulta en una versión de ClickHouse anterior a la 26.9.

Incompatibilidades conocidas

A pesar de corregir una gran cantidad de errores e introducir nuevas optimizaciones, también se introducen algunos cambios incompatibles en el comportamiento de ClickHouse. Lea los siguientes cambios para determinar cómo reescribir sus consultas para el analizador.

Las consultas no válidas ya no se optimizan

La infraestructura anterior de planificación de consultas aplicaba optimizaciones a nivel de AST antes del paso de validación de la consulta. Las optimizaciones podían reescribir la consulta inicial para que fuera válida y ejecutable. En el analizador, la validación de la consulta se realiza antes del paso de optimización. Esto significa que las consultas no válidas que antes podían ejecutarse ahora ya no se admiten. En esos casos, la consulta debe corregirse manualmente.

Ejemplo 1

La siguiente consulta usa la columna number en la lista de proyección cuando, tras la agregación, solo está disponible toString(number). En el analizador anterior, GROUP BY toString(number) se optimizaba a GROUP BY number,, lo que hacía que la consulta fuera válida.

Ejemplo 2

El mismo problema se produce en esta consulta. La columna number se usa después de la agregación con otra clave. El analizador de consultas anterior corrigió esta consulta al mover el filtro number > 5 de la cláusula HAVING a la cláusula WHERE.
Para corregir la consulta, debes mover a la sección WHERE todas las condiciones que se apliquen a columnas no agregadas, para ajustarte a la sintaxis SQL estándar:
Como ayuda para la migración, el analizador puede replicar la antigua reescritura de HAVING a WHERE para conjunciones AND no agregadas. Habilita analyzer_compatibility_allow_non_aggregate_in_having = 1 para activar este comportamiento. Esta configuración está disponible desde ClickHouse 26.7. La configuración se ignora para WITH CUBE, WITH ROLLUP, WITH TOTALS y GROUPING SETS. Las conjunciones que contienen funciones de agregación, grouping o no deterministas permanecen en HAVING; si alguna conjunción contiene una función de ventana o una función con estado (por ejemplo, rowNumberInBlock), la reescritura se desactiva para toda la cláusula HAVING, en consonancia con el comportamiento heredado.

CREATE VIEW con una consulta no válida

El analizador siempre realiza la verificación de tipos. Anteriormente, era posible crear una VIEW con una consulta SELECT no válida. El error aparecía durante el primer SELECT o INSERT (en el caso de MATERIALIZED VIEW). Ya no es posible crear una VIEW de esta forma.

Ejemplo

Incompatibilidades conocidas de la cláusula JOIN

JOIN usando una columna de una proyección

De forma predeterminada, no se puede usar un alias de la lista SELECT como clave de JOIN USING. Una nueva configuración, analyzer_compatibility_join_using_top_level_identifier, cuando está habilitada, cambia el comportamiento de JOIN USING para que dé prioridad a la resolución de identificadores a partir de las expresiones de la lista de proyección de la consulta SELECT, en lugar de usar directamente las columnas de la tabla de la izquierda. Por ejemplo:
Con analyzer_compatibility_join_using_top_level_identifier establecido en true, la condición de join se interpreta como t1.a + 1 = t2.b, en consonancia con el comportamiento de las versiones anteriores. El resultado será 2, 'two'. Cuando la configuración está en false, la condición de join pasa a ser t1.b = t2.b de forma predeterminada, y la consulta devolverá 2, 'one'. Si b no está presente en t1, la consulta fallará con un error.

Cambios de comportamiento con JOIN USING y columnas ALIAS/MATERIALIZED

En el analizador, usar * en una consulta JOIN USING que involucre columnas ALIAS o MATERIALIZED hará que esas columnas se incluyan en el conjunto de resultados de forma predeterminada. Por ejemplo:
En el analizador, el resultado de esta consulta incluirá la columna payload junto con id de ambas tablas. En cambio, el analizador anterior solo incluía estas columnas ALIAS si se habían habilitado opciones específicas (asterisk_include_alias_columns o asterisk_include_materialized_columns), y las columnas podían aparecer en un orden diferente. Para garantizar resultados coherentes y previsibles, especialmente al migrar consultas antiguas al analizador, es aconsejable especificar las columnas explícitamente en la cláusula SELECT en lugar de usar *.

Manejo de los modificadores de tipo de las columnas en la cláusula USING

En el analizador, se han estandarizado las reglas para determinar el supertipo común de las columnas especificadas en la cláusula USING, con el fin de producir resultados más predecibles, especialmente al trabajar con modificadores de tipo como LowCardinality y Nullable.
  • LowCardinality(T) y T: Cuando una columna de tipo LowCardinality(T) se combina con una columna de tipo T, el supertipo común resultante será T, lo que en la práctica descarta el modificador LowCardinality.
  • Nullable(T) y T: Cuando una columna de tipo Nullable(T) se combina con una columna de tipo T, el supertipo común resultante será Nullable(T), lo que garantiza que se conserve la propiedad Nullable.
Por ejemplo:
En esta consulta, el supertipo común de id se establece como String, descartando el modificador LowCardinality de t1.

Cambios en los nombres de las columnas de la proyección

Durante el cálculo de los nombres de la proyección, no se sustituyen los alias.
Antes de 24.3, la segunda columna recibía el nombre del alias sustituido:
El analizador conserva el alias en el nombre:

Tipos incompatibles en los argumentos de función

En el analizador, la inferencia de tipos se produce durante el análisis inicial de la consulta. Este cambio significa que las comprobaciones de tipos se realizan antes de la evaluación de cortocircuito; por lo tanto, los argumentos de la función if siempre deben tener un supertipo común. Por ejemplo, la siguiente consulta falla con There is no supertype for types Array(UInt8), String because some of them are Array and some of them are not:

Clústeres heterogéneos

El analizador cambia de forma significativa el protocolo de comunicación entre los servidores del clúster. Por lo tanto, es imposible ejecutar consultas distribuidas en servidores que no coincidan en si se usa el analizador, lo que, en un clúster de servidores anteriores a la versión 26.9, significa servidores con valores distintos de la SETTING enable_analyzer. Un servidor de la versión 26.10 o posterior ya no dispone de ningún otro análisis de consultas, por lo que ignora el valor que envía un iniciador más antiguo y analiza la consulta con el analizador de todos modos. Ambos análisis no nombran igual las columnas del resultado, y el iniciador hace coincidir el bloque que devuelve un segmento por el nombre de la columna, de modo que una consulta así puede fallar en el iniciador con NOT_FOUND_COLUMN_IN_BLOCK; por ejemplo, cuando selecciona una función escrita con una grafía no canónica (hostname()), que el analizador resuelve a su nombre canónico (hostName()). Por consiguiente, un clúster que siga funcionando con el análisis de consultas antiguo debe establecer enable_analyzer = 1 en todos los servidores antes de actualizar cualquiera de ellos a 26.10.

Funcionalidades no compatibles

A continuación se muestra la lista de funcionalidades que el analizador no admite actualmente:
  • Índice Annoy.
  • Índice Hypothesis. Trabajo en curso aquí.

Migración a Cloud

Estamos habilitando el analizador en todas las instancias donde actualmente está deshabilitado para permitir nuevas optimizaciones funcionales y de rendimiento. Este cambio impone reglas de ámbito de SQL más estrictas, por lo que los clientes deberán actualizar manualmente las consultas que no las cumplan.

Flujo de migración

  1. Identifique la consulta filtrando system.query_log con normalized_query_hash:
  1. Ejecute la consulta con el analizador, agregando la configuración de compatibilidad que restaura la resolución de identificadores del análisis anterior en los casos en que la consulta dependa de ella.
  1. Refactoriza y verifica los resultados de la consulta para asegurarte de que coincidan con la salida que producía la consulta antes de la migración.
Consulta las incompatibilidades más frecuentes detectadas durante las pruebas internas.

Identificador de expresión desconocido

Error: Unknown expression identifier ... in scope ... (UNKNOWN_IDENTIFIER). Código de excepción: 47 Causa: Las consultas que dependen de comportamientos heredados permisivos y no estándar, como hacer referencia a alias calculados en filtros, proyecciones ambiguas de subconsultas o un alcance “dinámico” de CTE, ahora se identifican correctamente como no válidas y se rechazan de inmediato. Solución: Actualice sus patrones SQL de la siguiente manera:
  • Lógica de filtro: Mueva la lógica de WHERE a HAVING si filtra por resultados, o duplique la expresión en WHERE si filtra por datos de origen.
  • Alcance de la subconsulta: Seleccione explícitamente todas las columnas necesarias para la consulta externa.
  • Claves de JOIN: Use ON con expresiones completas en lugar de USING si la clave es un alias.
  • En las consultas externas, haga referencia al alias de la propia subconsulta/CTE, no a las tablas que contiene.

Columnas no agregadas en GROUP BY

Error: Column ... is not under aggregate function and not in GROUP BY keys (NOT_AN_AGGREGATE). Código de excepción: 215 Causa: El analizador anterior permitía seleccionar columnas que no estaban presentes en la cláusula GROUP BY (a menudo tomando un valor arbitrario). El analizador sigue el estándar SQL: cada columna seleccionada debe ser un agregado o una clave de agrupación. Solución: Envuelva la columna en any(), argMax() o añádala a GROUP BY.

Columnas no agregadas en HAVING

Error: Column ... is not under aggregate function and not in GROUP BY keys (NOT_AN_AGGREGATE). código de excepción: 215 Causa: El analizador anterior movía silenciosamente a WHERE las conjunciones con AND de HAVING que no eran de agregación, tratándolas como filtros de preagregación. El analizador se ajusta al SQL estándar: HAVING solo puede hacer referencia a claves de agregación y funciones de agregación. Solución: Mueva manualmente el predicado de HAVING a WHERE, o habilite analyzer_compatibility_allow_non_aggregate_in_having = 1 (disponible desde ClickHouse 26.7) para restaurar la reescritura heredada como ayuda para la migración. La configuración compatibility se ignora para WITH CUBE, WITH ROLLUP, WITH TOTALS y GROUPING SETS. Las conjunciones que contienen funciones de agregación, grouping o funciones no deterministas permanecen en HAVING; si alguna conjunción contiene una función de ventana o una función con estado (por ejemplo, rowNumberInBlock), la reescritura se desactiva para todo el HAVING, en consonancia con el comportamiento heredado.

Nombres de CTE duplicados

Error: CTE with name ... already exists (MULTIPLE_EXPRESSIONS_FOR_ALIAS). Código de excepción: 179 Causa: El analizador anterior permitía definir varias expresiones de tabla comunes (Common Table Expressions, WITH …) con el mismo nombre, de modo que cada definición posterior ocultaba a la anterior. El analizador rechaza esta ambigüedad de forma predeterminada. Solución: Cambie el nombre de las CTE duplicadas para que sean únicos. Para facilitar la migración, puede habilitar analyzer_compatibility_allow_cte_redefinition = 1 (disponible desde ClickHouse 26.10) y restaurar así el comportamiento heredado: una referencia se vincula a la definición más reciente del nombre que no se esté resolviendo en ese momento, de modo que una redefinición puede leer la definición anterior y el cuerpo de la consulta lee la última. Limitaciones: una CTE declarada como MATERIALIZED y una CTE en una cláusula WITH RECURSIVE no pueden redefinirse, ni siquiera con el ajuste habilitado. Hay un caso en el que el comportamiento difiere del analizador anterior: una CTE declarada entre dos definiciones de un mismo nombre también se vincula a la última definición, mientras que el analizador anterior la vinculaba a la definición visible en el punto donde se declaraba.

Identificadores de columna ambiguos

Error: JOIN [JOIN TYPE] ambiguous identifier ... (AMBIGUOUS_IDENTIFIER) Código de excepción: 207 Causa: La consulta hace referencia a un nombre de columna presente en varias tablas dentro de un JOIN sin especificar la tabla de origen. El analizador antiguo a menudo deducía la columna según su lógica interna; el analizador requiere un nombre explícito. Solución: Especifique el nombre completo de la columna con table_alias.column_name.

Uso no válido de FINAL

Error: Table expression modifiers FINAL are not supported for subquery... o Storage ... doesn't support FINAL (UNSUPPORTED_METHOD). Códigos de excepción: 1, 181 Causa: FINAL es un modificador del almacenamiento de tablas (en concreto, [Shared]ReplacingMergeTree). El analizador rechaza FINAL cuando se aplica a:
  • Subconsultas o tablas derivadas (p. ej., FROM (SELECT …) FINAL).
  • Motores de tabla que no lo admiten (p. ej., SharedMergeTree).
Solución: Aplique FINAL solo a la tabla de origen dentro de la subconsulta, o elimínelo si el motor no lo admite.

Insensibilidad a mayúsculas y minúsculas en la función countDistinct()

Error: Function with name countdistinct does not exist (UNKNOWN_FUNCTION). Código de excepción: 46 Causa: Los nombres de las funciones son sensibles a mayúsculas y minúsculas o están asociados de forma estricta en el analizador. countdistinct (todo en minúsculas) ya no se resuelve automáticamente. Solución: Use countDistinct estándar (camelCase) o uniq, específico de ClickHouse.
Última modificación el 26 de septiembre de 2026