ON CLUSTER, que se describe por separado.
Variantes de sintaxis
Con esquema explícito
table_name en la base de datos db o en la base de datos actual si no se ha definido db, con la estructura especificada entre corchetes y el motor engine.
La estructura de la tabla es una lista de descripciones de columnas, índices secundarios, proyecciones y restricciones. Si el motor admite clave primaria, esta se indicará como parámetro del motor de tabla.
Una descripción de columna es name type en el caso más simple. Ejemplo: RegionID UInt32.
También se pueden definir expresiones para los valores predeterminados (véase más abajo).
Si es necesario, se puede especificar la clave primaria, con una o más expresiones de clave.
Se pueden añadir comentarios a las columnas y a la tabla.
Con el esquema de una tabla existente
Con el esquema y los datos de una tabla existente
db.table. En otras palabras, los datos de db.table se clonan en db2.table_clone en el momento de su creación. Esta consulta es equivalente a la siguiente:
db.table).
A partir de una función de tabla
A partir de una consulta SELECT
SELECT, usa el motor engine y la rellena con datos de SELECT. También puede especificar explícitamente la definición de las columnas.
Si la tabla ya existe y se especifica IF NOT EXISTS, la consulta no hará nada.
Puede haber otras cláusulas después de la cláusula ENGINE en la consulta. Consulte la documentación detallada sobre cómo crear tablas en las descripciones de los motores de tabla.
Ejemplo
Query
Response
Modificadores NULL o NOT NULL
NULL y NOT NULL después del tipo de dato en la definición de una columna permiten o impiden que sea Nullable.
Si el tipo no es Nullable y se especifica NULL, se tratará como Nullable; si se especifica NOT NULL, no. Por ejemplo, INT NULL es equivalente a Nullable(INT). Si el tipo es Nullable y se especifican los modificadores NULL o NOT NULL, se generará una excepción.
Véase también la opción de configuración data_type_default_nullable.
Valores predeterminados
DEFAULT expr, MATERIALIZED expr o ALIAS expr. Ejemplo: URLDomain String DEFAULT domain(URL).
La expresión expr es opcional. Si se omite, el tipo de la columna debe especificarse explícitamente y el valor predeterminado será 0 para las columnas numéricas, '' (la cadena vacía) para las columnas String, [] (el Array vacío) para las columnas Array, 1970-01-01 para las columnas de fecha o NULL para las columnas Nullable.
El tipo de la columna con valor predeterminado puede omitirse, en cuyo caso se infiere a partir del tipo de expr. Por ejemplo, el tipo de la columna EventDate DEFAULT toDate(EventTime) será date.
Si se especifican tanto un tipo de dato como una expresión de valor predeterminado, se inserta una función implícita de conversión de tipos que convierte la expresión al tipo especificado. Ejemplo: Hits UInt32 DEFAULT 0 se representa internamente como Hits UInt32 DEFAULT toUInt32(0).
Una expresión de valor predeterminado expr puede hacer referencia a columnas de tabla arbitrarias y constantes. ClickHouse comprueba que los cambios en la estructura de la tabla no introduzcan bucles en el cálculo de la expresión. Para INSERT, comprueba que las expresiones puedan resolverse; es decir, que se hayan pasado todas las columnas a partir de las cuales pueden calcularse.
DEFAULT
DEFAULT expr
Valor predeterminado normal. Si no se especifica el valor de una columna de este tipo en una consulta INSERT, se calcula a partir de expr.
Ejemplo:
MATERIALIZED
MATERIALIZED expr
Expresión materializada. Los valores de estas columnas se calculan automáticamente según la expresión materializada especificada cuando se insertan filas. Los valores no pueden especificarse explícitamente durante los INSERT.
Además, las columnas con valor predeterminado de este tipo no se incluyen en el resultado de SELECT *. Esto preserva el invariante de que el resultado de un SELECT * siempre puede volver a insertarse en la tabla mediante INSERT. Este comportamiento puede deshabilitarse con la configuración asterisk_include_materialized_columns.
Ejemplo:
EPHEMERAL
EPHEMERAL [expr]
Columna efímera. Las columnas de este tipo no se almacenan en la tabla y no es posible hacer SELECT de ellas. El único propósito de las columnas efímeras es utilizarlas para construir expresiones de valor predeterminado para otras columnas.
Una inserción sin columnas especificadas explícitamente omitirá las columnas de este tipo. Esto preserva la invariante de que el resultado de un SELECT * siempre puede volver a insertarse en la tabla mediante INSERT.
Ejemplo:
ALIAS
ALIAS expr
Columnas calculadas (sinónimo). Las columnas de este tipo no se almacenan en la tabla y no es posible insertar valores en ellas con INSERT.
Cuando las consultas SELECT hacen referencia explícita a columnas de este tipo, el valor se calcula en el momento de la consulta a partir de expr. De forma predeterminada, SELECT * excluye las columnas ALIAS. Este comportamiento se puede desactivar con el ajuste asterisk_include_alias_columns.
Al usar la consulta ALTER para añadir columnas nuevas, no se escriben los datos antiguos de esas columnas. En su lugar, al leer datos antiguos que no tienen valores para las columnas nuevas, las expresiones se calculan sobre la marcha de forma predeterminada. Sin embargo, si para ejecutar las expresiones se necesitan otras columnas que no se indican en la consulta, esas columnas también se leerán, pero solo para los bloques de datos que lo requieran.
Si añade una nueva columna a una tabla pero más tarde cambia su expresión por defecto, los valores usados para los datos antiguos cambiarán (para los datos cuyos valores no se almacenaron en disco). Tenga en cuenta que, al ejecutar fusiones en segundo plano, los datos de las columnas que faltan en una de las partes que se están fusionando se escriben en la parte fusionada.
No es posible establecer valores predeterminados para elementos de estructuras de datos anidadas.
Puede definir una clave primaria al crear una tabla. La clave primaria se puede especificar de dos maneras:
- En la lista de columnas
- Fuera de la lista de columnas
Restricciones
CONSTRAINT
boolean_expr_1 puede ser cualquier expresión booleana. Si se definen restricciones para la tabla, cada una de ellas se comprobará en cada fila de la consulta INSERT. Si alguna restricción no se cumple, el servidor lanzará una excepción con el nombre de la restricción y la expresión de comprobación.
Añadir una gran cantidad de restricciones puede afectar negativamente al rendimiento de consultas INSERT grandes.
ASSUME
ASSUME se utiliza para definir una CONSTRAINT sobre una tabla que se asume verdadera. Esta restricción puede ser utilizada posteriormente por el optimizador para mejorar el rendimiento de las consultas SQL.
Veamos este ejemplo en el que ASSUME CONSTRAINT se usa al crear la tabla users_a:
ASSUME CONSTRAINT se usa para indicar que la función length(name) siempre es igual al valor de la columna name_len. Esto significa que, cada vez que se llama a length(name) en una consulta, ClickHouse puede sustituirla por name_len, lo que debería ser más rápido porque evita llamar a la función length().
Luego, al ejecutar la consulta SELECT name FROM users_a WHERE length(name) < 5;, ClickHouse puede optimizarla como SELECT name FROM users_a WHERE name_len < 5; gracias a ASSUME CONSTRAINT. Esto puede hacer que la consulta se ejecute más rápido porque evita calcular la longitud de name para cada fila.
ASSUME CONSTRAINT no impone la restricción, simplemente informa al optimizador de que la restricción se cumple. Si la restricción en realidad no es cierta, los resultados de las consultas pueden ser incorrectos. Por lo tanto, solo debes usar ASSUME CONSTRAINT si estás seguro de que la restricción es cierta.
Expresión TTL
Códecs de compresión de columnas
lz4 en la versión autogestionada y zstd en ClickHouse Cloud.
En la familia de motores MergeTree, puede cambiar el método de compresión predeterminado en la sección compression de la configuración del servidor.
También puede definir el método de compresión para cada columna en la consulta CREATE TABLE.
Default puede especificarse para hacer referencia a la compresión predeterminada, que en tiempo de ejecución puede depender de distintos ajustes (y de las propiedades de los datos).
Ejemplo: value UInt64 CODEC(Default) — equivale a no especificar ningún códec.
También puede quitar el CODEC actual de la columna y usar la compresión predeterminada de config.xml:
CODEC(Delta, Default).
Se admite compresión en los siguientes motores de tabla:
- Familia MergeTree. Admite códecs de compresión por columna y la selección del método de compresión predeterminado mediante la configuración de compression.
- Familia Log. Usa el método de compresión
lz4de forma predeterminada y admite códecs de compresión por columna. - Set. Solo admite la compresión predeterminada.
- Join. Solo admite la compresión predeterminada.
Códecs de uso general
NONE
NONE — Sin compresión.
LZ4
LZ4 — Algoritmo de compresión de datos sin pérdida usado de forma predeterminada. Utiliza la compresión rápida LZ4.
LZ4HC
LZ4HC[(level)] — algoritmo LZ4 HC (alta compresión) con un nivel configurable. Nivel predeterminado: 9. La opción level <= 0 aplica el nivel predeterminado. Niveles posibles: [1, 12]. Rango de niveles recomendado: [4, 9].
ZSTD
ZSTD[(level)] — algoritmo de compresión ZSTD con level configurable. Niveles posibles: [1, 22]. Nivel predeterminado: 1.
Los niveles de compresión altos son útiles en escenarios asimétricos, como comprimir una vez y descomprimir repetidamente. Los niveles más altos implican una mejor compresión y un mayor uso de CPU.
Obsoleto: ZSTD_QAT
Obsoleto: DEFLATE_QPL
Códecs especializados
Delta
Delta(delta_bytes) — Método de compresión en el que los valores originales se sustituyen por la diferencia entre dos valores adyacentes, excepto el primero, que permanece sin cambios. delta_bytes es el tamaño máximo de los valores originales; el valor predeterminado es sizeof(type). Especificar delta_bytes como argumento está obsoleto y la compatibilidad se eliminará en una versión futura. Delta es un códec de preparación de datos, es decir, no puede usarse por sí solo.
DoubleDelta
DoubleDelta(bytes_size) — Calcula el delta de los deltas y lo escribe en formato binario compacto. bytes_size tiene un significado similar al de delta_bytes en el códec Delta. Especificar bytes_size como argumento está obsoleto y esta compatibilidad se eliminará en una versión futura. Se obtienen tasas de compresión óptimas para secuencias monótonas con un paso constante, como los datos de series temporales. Puede usarse con cualquier tipo numérico. Implementa el algoritmo utilizado en Gorilla TSDB y lo amplía para admitir tipos de 64 bits. Usa 1 bit adicional para deltas de 32 bits: prefijos de 5 bits en lugar de prefijos de 4 bits. Para obtener más información, consulte Compressing Time Stamps en Gorilla: A Fast, Scalable, In-Memory Time Series Database. DoubleDelta es un códec de preparación de datos; es decir, no puede usarse por sí solo.
GCD
GCD() - - Calcula el máximo común divisor (GCD) de los valores de la columna y, a continuación, divide cada valor por el GCD. Puede usarse con columnas de enteros, decimales y fecha/hora. El códec es especialmente adecuado para columnas con valores que cambian (aumentan o disminuyen) en múltiplos del GCD, p. ej., 24, 28, 16, 24, 8, 24 (GCD = 4). GCD es un códec de preparación de datos, es decir, no puede usarse por sí solo.
Gorilla
Gorilla(bytes_size) — Calcula el XOR entre el valor actual y el valor anterior de coma flotante, y lo escribe en formato binario compacto. Cuanto menor sea la diferencia entre valores consecutivos, es decir, cuanto más lentamente cambien los valores de la serie temporal, mejor será la tasa de compresión. Implementa el algoritmo utilizado en Gorilla TSDB y lo amplía para admitir tipos de 64 bits. Los valores posibles de bytes_size son: 1, 2, 4, 8; el valor predeterminado es sizeof(type) si es igual a 1, 2, 4 u 8. En todos los demás casos, es 1. Para obtener más información, consulte la sección 4.1 de Gorilla: A Fast, Scalable, In-Memory Time Series Database.
ALP
ALP() — Compresión adaptativa sin pérdidas para datos de coma flotante basada en el escalado decimal. ALP intenta representar cada valor como un entero escalado exacto mediante potencias de diez y, a continuación, comprime los enteros resultantes con Frame-of-Reference y empaquetado de bits. Los valores que no pueden representarse exactamente se almacenan como excepciones en bruto. Funciona mejor con números derivados de valores decimales (p. ej., mediciones, moneda). Es compatible con Float32 y Float64. Para obtener más información, consulte ALP: Adaptive lossless floating-point compression.
Este códec es experimental y requiere
SET allow_experimental_codecs = 1 para poder utilizarse.FPC
FPC(level, float_size) - Predice repetidamente el siguiente valor de coma flotante de la secuencia usando el mejor de dos predictores; luego aplica XOR entre el valor real y el valor predicho, y comprime el resultado suprimiendo los ceros iniciales. Al igual que Gorilla, es eficiente para almacenar una serie de valores de coma flotante que cambian lentamente. Para valores de 64 bits (double), FPC es más rápido que Gorilla; para valores de 32 bits, el rendimiento puede variar. Posibles valores de level: 1-28; el valor predeterminado es 12. Posibles valores de float_size: 4, 8; el valor predeterminado es sizeof(type) si el tipo es Float. En todos los demás casos, es 4. Para obtener una descripción detallada del algoritmo, consulte High Throughput Compression of Double-Precision Floating-Point Data.
T64
T64 — Enfoque de compresión que recorta los bits altos no utilizados de los valores en tipos de datos enteros (incluidos Enum, Date y DateTime). En cada paso de su algoritmo, el códec toma un bloque de 64 valores, los coloca en una matriz de 64x64 bits, la transpone, recorta los bits no utilizados de los valores y devuelve el resto como una secuencia. Los bits no utilizados son los bits que no difieren entre los valores máximo y mínimo en toda la parte de datos para la que se usa la compresión.
Los códecs DoubleDelta y Gorilla se usan en Gorilla TSDB como componentes de su algoritmo de compresión. El enfoque de Gorilla es eficaz en escenarios en los que hay una secuencia de valores que cambian lentamente junto con sus marcas de tiempo. Las marcas de tiempo se comprimen eficazmente con el códec DoubleDelta, y los valores se comprimen eficazmente con el códec Gorilla. Por ejemplo, para obtener una tabla almacenada de forma eficiente, puede crearla con la siguiente configuración:
Códecs de cifrado
AES_128_GCM_SIV
CODEC('AES-128-GCM-SIV') — Cifra los datos con AES-128 en modo GCM-SIV según RFC 8452.
AES-256-GCM-SIV
CODEC('AES-256-GCM-SIV') — Cifra los datos con AES-256 en modo GCM-SIV.
Estos códecs usan un nonce fijo y, por lo tanto, el cifrado es determinista. Esto los hace compatibles con motores con deduplicación, como ReplicatedMergeTree, pero tiene una debilidad: cuando el mismo bloque de datos se cifra dos veces, el texto cifrado resultante será exactamente el mismo, por lo que un adversario que pueda leer el disco podrá detectar esta equivalencia (aunque solo la equivalencia, sin obtener su contenido).
La mayoría de los motores, incluida la familia “*MergeTree”, crean archivos de índice en disco sin aplicar códecs. Esto significa que el texto en claro aparecerá en disco si se indexa una columna cifrada.
Si realiza una consulta SELECT que menciona un valor específico en una columna cifrada (como en su cláusula WHERE), el valor puede aparecer en system.query_log. Puede que le convenga deshabilitar el registro.
Si es necesario aplicar compresión, debe especificarse explícitamente. De lo contrario, solo se aplicará cifrado a los datos.
Tablas temporales
Tenga en cuenta que las tablas temporales no están replicadas. Como resultado, no hay garantía de que los datos insertados en una tabla temporal estén disponibles en otras réplicas. El caso de uso principal en el que las tablas temporales pueden resultar útiles es para consultar o combinar pequeños conjuntos de datos externos durante una sola sesión.
- Las tablas temporales desaparecen al finalizar la sesión, incluso si se pierde la conexión.
- Una tabla temporal usa el motor de tabla Memory cuando no se especifica ningún motor, y puede usar cualquier motor de tabla excepto los motores Replicated y
KeeperMap. - No se puede especificar la DB para una tabla temporal. Se crea fuera de las bases de datos.
- No es posible crear una tabla temporal con una consulta DDL distribuida en todos los servidores del clúster (usando
ON CLUSTER): esta tabla solo existe en la sesión actual. - Si una tabla temporal tiene el mismo nombre que otra y una consulta especifica el nombre de la tabla sin especificar la DB, se usará la tabla temporal.
- Para el procesamiento distribuido de consultas, las tablas temporales con motor Memory usadas en una consulta se pasan a los servidores remotos.
(GLOBAL) IN distribuido. Para obtener más información, consulte las secciones correspondientes
Es posible usar tablas con ENGINE = Memory en lugar de tablas temporales.
REPLACE TABLE
REPLACE permite actualizar una tabla de forma atómica.
Esta sentencia es compatible con los motores de base de datos
Atomic y Replicated,
que son los motores de base de datos predeterminados de ClickHouse y ClickHouse Cloud, respectivamente.SELECT que no recupere los datos no deseados;
después, eliminar la tabla antigua y cambiar el nombre de la nueva.
Este enfoque se muestra en el ejemplo siguiente:
REPLACE (si se usan los motores de base de datos predeterminados) para obtener el mismo resultado:
Sintaxis
Todas las formas sintácticas de la sentencia
CREATE también sirven para esta sentencia. Invocar REPLACE sobre una tabla inexistente provocará un error.Ejemplos:
- Local
- Cloud
Considere la siguiente tabla:Podemos usar la sentencia O bien podemos usar la sentencia
REPLACE para vaciar todos los datos:REPLACE para cambiar la estructura de la tabla:Cláusula COMMENT
La cláusula
COMMENT debe especificarse después de cualquier cláusula específica de almacenamiento, como PARTITION BY, ORDER BY y SETTINGS específicos del almacenamiento.Después de la cláusula COMMENT, solo se interpretarán los SETTINGS específicos de la consulta (como max_threads, etc.), no los ajustes relacionados con el almacenamiento.Esto significa que el orden correcto de las cláusulas es:ENGINE- cláusulas de almacenamiento
COMMENT- ajustes de la consulta (si los hay)
Query
Response