Esta página reúne ejemplos de índices de omisión de datos de ClickHouse y muestra cómo declarar cada tipo, cuándo usarlos y cómo verificar que se han aplicado. Todos funcionan con tablas de la familia MergeTree.
Sintaxis del índice:
INDEX name expr TYPE type(...) [GRANULARITY N]ClickHouse admite seis tipos de índices de omisión:
| Tipo de índice | Descripción |
|---|---|
| minmax | Hace un seguimiento de los valores mínimo y máximo de cada gránulo |
| set(N) | Almacena hasta N valores distintos por gránulo |
| text | Índice invertido sobre datos de texto tokenizados para búsqueda de texto completo |
| bloom_filter([false_positive_rate]) | Filtro probabilístico para comprobaciones de existencia |
| ngrambf_v1 | Filtro bloom de n-gramas para búsquedas de subcadenas |
| tokenbf_v1 | Filtro bloom basado en tokens para búsquedas de texto completo |
Cada sección ofrece ejemplos con datos de ejemplo y muestra cómo verificar el uso del índice durante la ejecución de consultas.
Índice MinMax
El índice minmax es más adecuado para predicados de rango en datos poco ordenados o en columnas correlacionadas con ORDER BY.
-- Definir en CREATE TABLE
CREATE TABLE events
(
ts DateTime,
user_id UInt64,
value UInt32,
INDEX ts_minmax ts TYPE minmax GRANULARITY 1
)
ENGINE=MergeTree
ORDER BY ts;
-- O agregar después y materializar
ALTER TABLE events ADD INDEX ts_minmax ts TYPE minmax GRANULARITY 1;
ALTER TABLE events MATERIALIZE INDEX ts_minmax;
-- Consulta que se beneficia del índice
SELECT count() FROM events WHERE ts >= now() - 3600;
-- Verificar uso
EXPLAIN indexes = 1
SELECT count() FROM events WHERE ts >= now() - 3600;Consulta un ejemplo detallado con EXPLAIN y poda.
Índice set
Utiliza el índice set cuando la cardinalidad local (por bloque) sea baja; no es útil si cada bloque tiene muchos valores distintos.
ALTER TABLE events ADD INDEX user_set user_id TYPE set(100) GRANULARITY 1;
ALTER TABLE events MATERIALIZE INDEX user_set;
SELECT * FROM events WHERE user_id IN (101, 202);
EXPLAIN indexes = 1
SELECT * FROM events WHERE user_id IN (101, 202);En la guía básica de funcionamiento se muestran un flujo de trabajo de creación/materialización y su efecto antes y después.
Índice de texto (text) para búsqueda de texto completo
text es un índice invertido sobre datos de texto tokenizados.
Está diseñado específicamente para cargas de trabajo de búsqueda de texto completo, lo que permite una búsqueda eficiente y determinista de tokens y términos.
Se recomienda para casos de uso de lenguaje natural o de búsqueda de texto a gran escala.
Consulta Búsqueda de texto completo con índices de texto para obtener más detalles y ejemplos.
ALTER TABLE logs ADD INDEX msg_text msg TYPE text(tokenizer = splitByNonAlpha);
ALTER TABLE logs MATERIALIZE INDEX msg_text;
SELECT count() FROM logs WHERE hasAllTokens(msg, 'exception');Consulte en la documentación un ejemplo más completo de observabilidad aquí.
El índice de texto es totalmente determinista y completamente configurable en términos de tokenización y procesamiento de texto, a costa de un mayor consumo de almacenamiento en comparación con los índices basados en bloom filter,
Filtro Bloom genérico (escalar)
El índice bloom_filter es adecuado para búsquedas de igualdad o pertenencia en IN del tipo "aguja en un pajar". Acepta un parámetro opcional, que es la tasa de falsos positivos (valor predeterminado: 0.025).
ALTER TABLE events ADD INDEX value_bf value TYPE bloom_filter(0.01) GRANULARITY 3;
ALTER TABLE events MATERIALIZE INDEX value_bf;
SELECT * FROM events WHERE value IN (7, 42, 99);
EXPLAIN indexes = 1
SELECT * FROM events WHERE value IN (7, 42, 99);Filtro Bloom de n-gramas (ngrambf_v1) para la búsqueda de subcadenas (Obsoleto)
El índice ngrambf_v1 divide las cadenas en n-gramas. Funciona bien para consultas LIKE '%...%'. Admite String/FixedString/Map (mediante mapKeys/mapValues), así como un tamaño configurable, número de funciones hash y semilla. Consulta la documentación de N-gram bloom filter para más detalles.
-- Crear índice para búsqueda de subcadenas
ALTER TABLE logs ADD INDEX msg_ngram msg TYPE ngrambf_v1(3, 10000, 3, 7) GRANULARITY 1;
ALTER TABLE logs MATERIALIZE INDEX msg_ngram;
-- Búsqueda de subcadenas
SELECT count() FROM logs WHERE msg LIKE '%timeout%';
EXPLAIN indexes = 1
SELECT count() FROM logs WHERE msg LIKE '%timeout%';Esta guía muestra ejemplos prácticos y cuándo usar token o ngram.
Herramientas para optimizar parámetros:
Los cuatro parámetros de ngrambf_v1 (tamaño del n-gram, tamaño del bitmap, funciones hash y semilla) influyen significativamente en el rendimiento y el consumo de memoria. Utilice estas funciones para calcular el tamaño óptimo del bitmap y la cantidad de funciones hash en función del volumen esperado de n-grams y de la tasa de falsos positivos deseada:
CREATE FUNCTION bfEstimateFunctions AS
(total_grams, bits) -> round((bits / total_grams) * log(2));
CREATE FUNCTION bfEstimateBmSize AS
(total_grams, p_false) -> ceil((total_grams * log(p_false)) / log(1 / pow(2, log(2))));
-- Ejemplo de dimensionamiento para 4300 ngrams, p_false = 0.0001
SELECT bfEstimateBmSize(4300, 0.0001) / 8 AS size_bytes; -- ~10304
SELECT bfEstimateFunctions(4300, bfEstimateBmSize(4300, 0.0001)) AS k; -- ~13Consulte la documentación de parámetros para obtener una guía completa de optimización.
Filtro Bloom de tokens (tokenbf_v1) para búsquedas por palabras (Obsoleto)
tokenbf_v1 indexa tokens separados por caracteres no alfanuméricos. Debe usarse con hasToken, patrones de palabras con LIKE o equals/IN. Es compatible con los tipos String/FixedString/Map.
Consulta las páginas Filtro Bloom de tokens y Tipos de filtros Bloom para obtener más información.
ALTER TABLE logs ADD INDEX msg_token lower(msg) TYPE tokenbf_v1(10000, 7, 7) GRANULARITY 1;
ALTER TABLE logs MATERIALIZE INDEX msg_token;
-- Búsqueda de palabras (sin distinción de mayúsculas/minúsculas mediante lower)
SELECT count() FROM logs WHERE hasToken(lower(msg), 'exception');
EXPLAIN indexes = 1
SELECT count() FROM logs WHERE hasToken(lower(msg), 'exception');Consulte ejemplos de observabilidad y recomendaciones sobre token frente a ngram aquí.
Agregar índices durante CREATE TABLE (varios ejemplos)
Los índices de omisión también admiten expresiones compuestas y tipos Map/Tuple/Nested. Esto se demuestra en el ejemplo siguiente:
CREATE TABLE t
(
u64 UInt64,
s String,
m Map(String, String),
INDEX idx_bf u64 TYPE bloom_filter(0.01) GRANULARITY 3,
INDEX idx_minmax u64 TYPE minmax GRANULARITY 1,
INDEX idx_set u64 * length(s) TYPE set(1000) GRANULARITY 4,
INDEX idx_ngram s TYPE ngrambf_v1(3, 10000, 3, 7) GRANULARITY 1,
INDEX idx_token mapKeys(m) TYPE tokenbf_v1(10000, 7, 7) GRANULARITY 1
)
ENGINE = MergeTree
ORDER BY u64;Materializar datos existentes y verificarlo
Puedes añadir un índice a las partes de datos existentes con MATERIALIZE y examinar la poda con EXPLAIN o con logs de nivel trace, como se muestra a continuación:
ALTER TABLE t MATERIALIZE INDEX idx_bf;
EXPLAIN indexes = 1
SELECT count() FROM t WHERE u64 IN (123, 456);
-- Opcional: información detallada de pruning
SET send_logs_level = 'trace';Este ejemplo práctico de minmax muestra la estructura de la salida de EXPLAIN y cuántos elementos se descartan.
Cuándo usar y cuándo evitar los índices de omisión
Use índices de omisión cuando:
- Los valores de filtro son dispersos dentro de los bloques de datos
- Existe una fuerte correlación con las columnas de
ORDER BY, o los patrones de ingestión de datos agrupan valores similares - Se realizan búsquedas de texto en grandes conjuntos de logs (tipos
ngrambf_v1/tokenbf_v1)
Evite los índices de omisión cuando:
- Es probable que la mayoría de los bloques contengan al menos un valor coincidente (los bloques se leerán de todos modos)
- Se filtra por columnas de alta cardinalidad sin correlación con el orden de los datos
Ignorar temporalmente o forzar índices
Deshabilite índices específicos por nombre para consultas individuales durante las pruebas y la solución de problemas. También hay ajustes para forzar el uso de índices cuando sea necesario. Consulte ignore_data_skipping_indices.
-- Ignore an index by name
SELECT * FROM logs
WHERE hasToken(lower(msg), 'exception')
SETTINGS ignore_data_skipping_indices = 'msg_token';Notas y advertencias
- Los índices de omisión solo son compatibles con las tablas de la familia MergeTree; la poda se realiza a nivel de gránulo/bloque.
- Los índices basados en filtros de Bloom son probabilísticos (los falsos positivos generan lecturas adicionales, pero no omiten datos válidos).
- Los filtros de Bloom y otros índices de omisión deben validarse con
EXPLAINy tracing; ajuste la granularidad para equilibrar la poda y el tamaño del índice.