Introducción
Funcionamiento básico
- Nombre del índice. El nombre del índice se usa para crear el archivo de índice en cada partición. Además, es un parámetro obligatorio al eliminar o materializar el índice.
- Expresión del índice. La expresión del índice se usa para calcular el conjunto de valores almacenados en el índice. Puede ser una combinación de columnas, operadores simples o un subconjunto de funciones determinado por el tipo de índice.
- TYPE. El tipo de índice controla el cálculo que determina si es posible omitir la lectura y evaluación de cada bloque de índice.
- GRANULARITY. Cada bloque indexado consta de GRANULARITY gránulos. Por ejemplo, si la granularidad del índice primario de la tabla es de 8192 filas y la granularidad del índice es 4, cada “bloque” indexado tendrá 32768 filas.
skp_idx_{index_name}.idx, que contiene los valores ordenados de la expresiónskp_idx_{index_name}.mrk2, que contiene los desplazamientos correspondientes dentro de los archivos de datos de columnas asociados.
my_value:
my_value de 125, y cómo las filas siguientes
se omitieron sin leer del disco:
Puede acceder a información detallada sobre el uso del índice de omisión de datos habilitando la traza al ejecutar consultas. Desde
clickhouse-client, establezca send_logs_level:
Tipos de índices de omisión
minmax
set
texto
hasAnyToken y hasAllTokens, además de optimizar las funciones comunes de búsqueda de texto.
Consulte la documentación del índice de texto para obtener más detalles aquí.
Tipos de filtros Bloom
- El bloom_filter básico, que acepta un único parámetro opcional correspondiente a la tasa permitida de “falsos positivos” entre 0 y 1 (si no se especifica, se usa .025).
-
El tokenbf_v1 especializado (Obsoleto)). Acepta tres parámetros, todos relacionados con el ajuste del filtro Bloom utilizado: (1) el tamaño del filtro en bytes (los filtros más grandes tienen menos falsos positivos, con cierto coste de almacenamiento), (2) el número de funciones hash aplicadas (de nuevo, más funciones hash reducen los falsos positivos) y (3) la semilla de las funciones hash del filtro Bloom. Consulta la calculadora aquí para obtener más información sobre cómo estos parámetros afectan al funcionamiento del filtro Bloom.
Este índice solo funciona con los tipos de datos String, FixedString y Map. La expresión de entrada se divide en secuencias de caracteres separadas por caracteres no alfanuméricos. Por ejemplo, un valor de columna de
This is a candidate for a "full text" searchcontendrá los tokensThisisacandidateforfulltextsearch. Está pensado para usarse en búsquedas LIKE, EQUALS, IN, hasToken() y otras similares de palabras y otros valores dentro de cadenas más largas. Por ejemplo, un posible uso sería buscar un pequeño número de nombres de clase o números de línea en una columna con líneas de log de aplicaciones sin estructura. -
El ngrambf_v1 especializado (Obsoleto). Este índice funciona igual que el índice de tokens. Acepta un parámetro adicional antes de la configuración del filtro Bloom: el tamaño de los ngrams que se van a indexar. Un ngram es una cadena de caracteres de longitud
nformada por cualquier carácter, por lo que la cadenaA short stringcon un tamaño de ngram de 4 se indexaría como:
Para cargas de trabajo de búsqueda de texto completo, se recomienda el índice de texto específico (consulta Text index for full-text search) en lugar de los índices obsoletos tokenbf_v1 o ngrambf_v1. El índice de texto proporciona un verdadero índice invertido con mejor rendimiento de búsqueda, un comportamiento más predecible y mayor flexibilidad y rendimiento en comparación con los índices de filtro Bloom basados en tokens.
Funciones de los índices de omisión
- se insertan datos y el índice se define como una expresión funcional (con el resultado de la expresión almacenado en los archivos de índice), o
- se procesa la consulta y la expresión se aplica a los valores almacenados en el índice para determinar si debe excluirse el bloque.
Configuración de los índices de omisión
- use_skip_indexes (0 o 1; valor predeterminado: 1). No todas las consultas pueden usar índices de omisión de forma eficiente. Si es probable que una condición de filtrado concreta incluya la mayoría de los gránulos, aplicar el índice de omisión de datos supone un costo innecesario y, en ocasiones, significativo. Establezca el valor en 0 para las consultas que probablemente no se beneficien de ningún índice de omisión.
- force_data_skipping_indices (lista de nombres de índices separados por comas). Esta configuración puede usarse para evitar algunos tipos de consultas ineficientes. En situaciones en las que consultar una tabla resulta demasiado costoso a menos que se use un índice de omisión, usar esta configuración con uno o más nombres de índice hará que se devuelva una excepción para cualquier consulta que no use el índice indicado en la lista. Esto evitaría que consultas mal escritas consuman recursos del servidor.
Prácticas recomendadas para los índices de omisión
timestamp y que hay un índice sobre visitor_id. Considere la siguiente consulta:
visitor_id
independientemente del tipo de índice de omisión.
En consecuencia, el impulso natural de intentar acelerar las consultas de ClickHouse simplemente añadiendo un índice a las
columnas clave suele ser erróneo. Esta funcionalidad avanzada solo debe usarse después de estudiar otras alternativas, como modificar la clave primaria (consulte Cómo elegir una clave primaria), usar proyecciones o usar vistas materializadas. Incluso cuando un índice de omisión de datos sea apropiado, a menudo será necesario ajustar cuidadosamente tanto el índice como la tabla.
En la mayoría de los casos, un índice de omisión útil requiere una fuerte correlación entre la clave primaria y la columna o expresión objetivo que no forma parte de la clave primaria.
Si no existe correlación (como en el diagrama anterior), es muy probable que al menos una de las filas del
bloque de varios miles de valores cumpla la condición de filtrado, y se omitirán pocos bloques. En cambio, si un rango de valores de la clave primaria (como la hora del
día) está estrechamente asociado con los valores de la posible columna del índice (como las edades de los televidentes), entonces es probable que un índice de tipo minmax
resulte beneficioso. Tenga en cuenta que puede ser posible aumentar esta correlación al insertar datos, ya sea incluyendo columnas adicionales
en la clave de ordenación/ORDER BY, o agrupando las inserciones de modo que los valores asociados con la clave primaria queden agrupados durante la inserción. Por
ejemplo, todos los eventos de un site_id concreto podrían agruparse e insertarse juntos mediante el proceso de ingesta, incluso si la clave primaria
es un timestamp que contiene eventos de un gran número de sitios. Esto dará lugar a muchos gránulos que contienen solo unos pocos site ids, por lo que muchos
bloques podrían omitirse al buscar un valor específico de site_id.
Otro buen candidato para un índice de omisión son las expresiones de alta cardinalidad en las que cualquier valor individual está relativamente disperso en los datos. Un ejemplo
podría ser una plataforma de observabilidad que rastrea códigos de error en solicitudes de API. Determinados códigos de error, aunque son poco frecuentes en los datos, podrían ser particularmente
importantes para las búsquedas. Un índice de omisión de tipo set en la columna error_code permitiría omitir la gran mayoría de los bloques que no contienen
errores y, por tanto, mejorar significativamente las consultas centradas en errores.
Por último, la mejor práctica fundamental es probar, probar y probar. De nuevo, a diferencia de los índices secundarios b-tree o de los índices invertidos para buscar documentos,
el comportamiento de los índices de omisión de datos no es fácil de predecir. Añadirlos a una tabla implica un coste considerable tanto en la ingesta de datos como en las consultas
que, por cualquier motivo, no se benefician del índice. Siempre deben probarse con datos representativos del mundo real, y las pruebas deben
incluir variaciones del tipo, el tamaño de granularidad y otros parámetros. Las pruebas a menudo revelan patrones y obstáculos que no resultan evidentes con
experimentos mentales únicamente.