Descripción general de las proyecciones
Las proyecciones almacenan los datos en un formato que optimiza la ejecución de consultas. Esta funcionalidad resulta útil para lo siguiente:- Ejecutar consultas sobre una columna que no forma parte de la clave primaria
- Preagregar columnas, lo que reduce tanto el cómputo como la E/S
Uso de discoLas proyecciones crean internamente una nueva tabla oculta, lo que implica más E/S y más espacio en disco.
Por ejemplo, si la proyección define una clave primaria diferente, todos los datos de la tabla original se duplicarán.
Uso de las proyecciones
Ejemplo de filtrado sin usar claves primarias
Creación de la tabla:ALTER TABLE, podemos añadir la proyección a una tabla existente:
user_name, incluso si en la tabla original user_name no estaba definido como PRIMARY_KEY.
En tiempo de consulta, ClickHouse determina que se procesarán menos datos si se utiliza la proyección, ya que los datos están ordenados por user_name.
system.query_log. En el campo projections aparece el nombre de la proyección utilizada, o queda vacío si no se ha usado ninguna:
Ejemplo de consulta de preagregación
Cree la tabla con la proyecciónprojection_visits_by_user:
GROUP BY usando el campo user_agent.
Esta consulta no aprovechará la proyección definida, ya que la agregación previa no coincide.
GROUP BY:
system.query_log para comprobar si se utilizó una proyección.
El campo projections muestra el nombre de la proyección utilizada.
Estará vacío si no se ha utilizado ninguna proyección:
Creación y uso de índices de proyección
Para crear un índice de proyección:_part_offset conserva su valor tras las fusiones y mutaciones, lo que lo hace útil para la indexación secundaria. Podemos aprovecharlo en las consultas:
Proyección de ejemplo con cláusula WHERE
Las proyecciones pueden incluir una cláusula WHERE para almacenar solo un subconjunto de filas. Esto resulta útil cuando las consultas filtran con frecuencia según un predicado conocido: la proyección materializa únicamente las filas que coinciden, lo que reduce el almacenamiento y mejora el rendimiento de las consultas.
Crear una tabla y añadir una proyección filtrada:
WHERE de una consulta implica la cláusula WHERE de la proyección (es decir, cada condición del filtro de la proyección también está presente en el filtro de la consulta), el optimizador puede usar automáticamente la proyección cuando determina que resulta beneficioso:
Gestión de proyecciones
Están disponibles las siguientes operaciones con proyecciones:ADD PROJECTION
Use la siguiente sentencia para añadir la descripción de una proyección a los metadatos de una tabla:Cuando una proyección define una cláusula
WHERE, solo se materializan las filas que cumplen el predicado. El optimizador puede usar esa proyección cuando el WHERE de la consulta implica lógicamente el WHERE de la proyección y esta resulta ventajosa para el plan de consulta. Esto se aplica tanto a las proyecciones normales como a las de agregación.Cláusula WITH SETTINGS
WITH SETTINGS define ajustes a nivel de proyección, que personalizan cómo la proyección almacena los datos (por ejemplo, index_granularity o index_granularity_bytes).
Estos corresponden directamente a los ajustes de tabla de MergeTree, pero se aplican solo a esta proyección.
Ejemplo:
MODIFY PROJECTION
Utilice la siguiente sentencia para modificar la cláusulaWITH SETTINGS de una proyección existente sin reconstruir sus datos:
INDEX en lugar de la consulta SELECT:
WITH SETTINGS puede diferir de la definición actual.
La consulta de la proyección (o, en el caso de un índice de proyección, la expresión y el tipo del índice) debe permanecer igual, ya que las partes de proyección existentes almacenan datos generados a partir de ella; para modificarla, use DROP PROJECTION seguido de ADD PROJECTION.
El comando solo modifica los metadatos de la tabla y no reescribe datos: las partes de proyección existentes conservan los ajustes con los que se escribieron, mientras que las partes de proyección creadas por futuras inserciones y fusiones usan los nuevos ajustes.
MATERIALIZE PROJECTION tampoco aplica los nuevos ajustes a las partes existentes: solo genera la proyección en las partes donde falta o está dañada, y deja sin cambios las partes de proyección que ya existen.
Para reconstruir las partes existentes con los nuevos ajustes, ejecute CLEAR PROJECTION seguido de MATERIALIZE PROJECTION, o fusione las partes, por ejemplo, con OPTIMIZE TABLE ... FINAL.
Ejemplo:
DROP PROJECTION
Utilice la siguiente sentencia para eliminar la descripción de una proyección de los metadatos de una tabla y borrar del disco los archivos de la proyección. Esto se implementa como una mutación.MATERIALIZE PROJECTION
Utilice la siguiente sentencia para construir la proyecciónname en las partes en las que falte o esté dañada, opcionalmente solo en la partición partition_name.
Las partes que ya tienen la proyección no se modifican, aunque los ajustes de la proyección se hayan cambiado con MODIFY PROJECTION después de que se escribieran; para reconstruirlas, ejecute primero CLEAR PROJECTION.
Esto se implementa como una mutación.
CLEAR PROJECTION
Use la sentencia siguiente para eliminar del disco los archivos de la proyección sin eliminar su descripción. Esto se implementa como una mutación.ADD, MODIFY, DROP y CLEAR son ligeros en el sentido de que solo modifican metadatos o eliminan archivos.
Además, se replican y sincronizan los metadatos de las proyecciones mediante ClickHouse Keeper o ZooKeeper.
La manipulación de proyecciones solo se admite en tablas con motor
*MergeTree (incluidas las variantes replicadas).Control del comportamiento de las fusiones de proyecciones
Cuando ejecuta una consulta, ClickHouse elige entre leer de la tabla original o de una de sus proyecciones. La decisión de leer de la tabla original o de una de sus proyecciones se toma de forma individual para cada parte de la tabla. Por lo general, ClickHouse intenta leer la menor cantidad de datos posible y emplea un par de técnicas para identificar la mejor parte desde la que leer; por ejemplo, el muestreo de la clave primaria de una parte. En algunos casos, las partes de la tabla de origen no tienen partes de proyección correspondientes. Esto puede ocurrir, por ejemplo, porque la creación de una proyección para una tabla en SQL es “perezosa” de forma predeterminada: solo afecta a los datos nuevos que se insertan, pero deja intactas las partes existentes. Como una de las proyecciones ya contiene los valores agregados precalculados, ClickHouse intenta leer de las partes de proyección correspondientes para evitar volver a agregar durante la ejecución de la consulta. Si una parte concreta no tiene la parte de proyección correspondiente, la ejecución de la consulta recurre a la parte original. Pero, ¿qué ocurre si las filas de la tabla original cambian de una forma no trivial debido a fusiones en segundo plano no triviales de partes de datos? Por ejemplo, suponga que la tabla se almacena usando el motor de tablaReplacingMergeTree.
Si se detecta la misma fila en varias partes de entrada durante la fusión, solo se conservará la versión más reciente de la fila (la de la parte insertada más recientemente), mientras que todas las versiones anteriores se descartarán.
De forma similar, si la tabla se almacena usando el motor de tabla AggregatingMergeTree, la operación de fusión puede combinar las mismas filas de las partes de entrada (según los valores de la clave primaria) en una sola fila para actualizar los estados de agregación parciales.
Antes de ClickHouse v24.8, las partes de proyección o bien quedaban desincronizadas silenciosamente con los datos principales, o bien ciertas operaciones, como actualizaciones y eliminaciones, no podían ejecutarse en absoluto, ya que la base de datos lanzaba automáticamente una excepción si la tabla tenía proyecciones.
Desde la versión v24.8, una nueva configuración a nivel de tabla deduplicate_merge_projection_mode controla el comportamiento cuando las operaciones en segundo plano de fusión no triviales mencionadas anteriormente se producen en partes de la tabla original.
Las mutaciones de eliminación son otro ejemplo de operaciones de fusión de partes que eliminan filas en las partes de la tabla original. Desde la versión v24.7, también disponemos de una configuración para controlar el comportamiento con respecto a las mutaciones de eliminación activadas por eliminaciones ligeras: lightweight_mutation_projection_mode.
A continuación se indican los posibles valores tanto de deduplicate_merge_projection_mode como de lightweight_mutation_projection_mode:
throw(predeterminado): Se lanza una excepción, lo que evita que las partes de proyección queden desincronizadas.drop: Se eliminan las partes afectadas de la tabla de proyección. Las consultas recurrirán a la parte de la tabla original para las partes de proyección afectadas.rebuild: La parte de proyección afectada se reconstruye para mantener la coherencia con los datos de la parte de la tabla original.
Limitaciones
No se puede usar una columnaALIAS en la cláusula ORDER BY de una proyección. Por ejemplo:
ALIAS no se almacenan físicamente y se calculan sobre la marcha en el momento de la consulta, por lo que no están disponibles durante la fase de escritura de partes de la proyección, cuando se evalúa la expresión de ordenación.
En su lugar, use columnas MATERIALIZED o escriba la expresión directamente en línea: