Skip to main content
Esta guía aplica dos enfoques de optimización al conjunto de datos NYC Taxi. Primero, reduce la cantidad de datos almacenados y procesados mediante la elección de tipos de columna más precisos. A continuación, introduce una clave de ordenación que permite a ClickHouse omitir datos en consultas selectivas. Cada cambio se mide con respecto a la misma referencia. Consulte la descripción general de la optimización de consultas para conocer el flujo de trabajo general que sigue este ejemplo.

Antes de empezar

Los ejemplos usan la tabla nyc_taxi.trips_small_inferred. Créela y cárguela si aún no lo ha hecho:
El archivo Parquet de origen ocupa aproximadamente 5,8 GB. La carga puede tardar varios minutos, según la red y los recursos disponibles.
El archivo Parquet de origen contiene aproximadamente 329 millones de filas. Los tiempos de esta guía se registraron en una implementación y variarán según los recursos de procesamiento disponibles. Compare el cambio relativo entre las etapas en lugar de esperar duraciones idénticas. Al aplicar este método a su propia carga de trabajo, use Diagnosticar consultas lentas para identificar un patrón de consulta recurrente y seleccionar una ejecución representativa antes de modificar la consulta o el esquema.

Descripción general del proceso

El ejemplo consta de las tres etapas siguientes:
  1. Ejecute tres consultas independientes de carga de trabajo sobre el esquema inferido para establecer una referencia.
  2. Cree una tabla con tipos de columna más precisos, cargue los mismos datos y vuelva a ejecutar las consultas.
  3. Cree otra tabla con el mismo esquema optimizado y una clave de ordenación, y vuelva a ejecutar las consultas.
Cambiar el esquema y la clave de ordenación en etapas separadas permite distinguir más fácilmente sus efectos. Enfoques de optimización explica cuándo conviene considerar estos cambios y cómo validarlos. Para obtener más orientación sobre cómo recopilar mediciones comparables, consulte Aislar los cuellos de botella de las consultas.

Defina la carga de trabajo de referencia

En la misma sesión del cliente utilizada para ejecutar la carga de trabajo, desactive la caché del sistema de archivos para datos remotos, la caché de consultas y la caché de condiciones de consulta:
Estos ajustes ayudan a que las ejecuciones repetidas sean comparables durante las pruebas. Restaure los valores anteriores una vez completadas las mediciones.
Las tres consultas independientes siguientes constituyen la carga de trabajo de referencia. Ejecute las tres en cada tabla creada en las etapas siguientes. Ejecute cada consulta varias veces en condiciones comparables y registre una duración representativa, como la mediana, junto con las filas leídas y el uso máximo de memoria. Consulte Establecer una línea de referencia repetible para conocer el flujo de trabajo de medición completo, incluido cómo recuperar estos valores de system.query_log.

Filtrar por velocidad de trayecto calculada

Esta consulta calcula la duración y la velocidad del trayecto antes de obtener la distribución de las distancias de los trayectos realizados a más de 30 millas por hora:

Agregar viajes en un intervalo de fechas

Esta consulta calcula el número de viajes, la distancia y los importes de pago medios del primer trimestre de 2009:

Filtrar por número de pasajeros

Esta consulta calcula la duración media de los viajes con uno o dos pasajeros:
Las mediciones iniciales fueron: Las tres consultas leyeron aproximadamente 329 millones de filas, una cifra cercana al número de filas de la tabla. Esto permite mejorar dos aspectos distintos de la carga de trabajo: reducir el coste de procesar las columnas seleccionadas y, después, reducir el número de filas seleccionadas cuando los filtros lo permitan.

Optimizar el esquema

La inferencia de esquemas es una forma práctica de empezar a explorar un conjunto de datos, pero los tipos inferidos pueden ser más amplios o permisivos de lo que exige la carga de trabajo. Inspeccione los datos antes de modificar el esquema, en lugar de dar por sentado que un tipo inferido es innecesario.

Evite columnas Nullable innecesarias

Una columna Nullable almacena una máscara de valores nulos además de los valores propiamente dichos. Mantenga Nullable cuando sea relevante distinguir entre un valor nulo y el valor predeterminado del tipo, pero evítelo en las columnas que siempre contengan un valor. Cuente los valores nulos de las columnas utilizadas en el esquema de ejemplo:
Solo ratecode_id, mta_tax y payment_type contienen valores nulos en este conjunto de datos. El esquema optimizado conserva Nullable en esas columnas y lo elimina de las demás.

Use LowCardinality para valores repetidos

LowCardinality utiliza codificación de diccionario y puede reducir el almacenamiento y el procesamiento de columnas con muchos valores repetidos. Compruebe el número de valores distintos antes de aplicarlo:
Estas cuatro columnas contienen considerablemente menos valores distintos que filas. Son buenas candidatas para LowCardinality, aunque conviene medir su efecto en la carga de trabajo. Unos 10.000 valores distintos constituyen un punto de partida útil para identificar candidatas, no un límite fijo.

Elige tipos de datos más precisos

Usa el tipo más específico que preserve de forma segura el rango y la precisión necesarios. Por ejemplo, examina los valores mínimo y máximo de las columnas numéricas antes de reemplazar un Int64 o Float64 inferido:
Ambas columnas de tipo entero caben en UInt8, aunque passenger_count alcanza el valor máximo de 255. El ejemplo también utiliza Float32 para trip_distance y Decimal32 para los valores monetarios. Todos los valores de este conjunto de datos caben dentro de los rangos de destino, y el ejemplo acepta la menor precisión de coma flotante y la precisión monetaria a nivel de céntimos porque su carga de trabajo compara resultados agregados. Conserve los tipos de origen más amplios cuando se requieran valores exactos de origen. El ejemplo sustituye las columnas DateTime64 inferidas por DateTime en la misma zona horaria UTC, ya que las consultas del ejemplo no requieren precisión de fracciones de segundo. Estas opciones son específicas de este conjunto de datos. Confirme los requisitos de rango, precisión y nulabilidad de los datos de producción antes de aplicar los mismos cambios.

Aplicar los cambios en el esquema

Cree una tabla sin una clave de ordenación para que esta etapa mida los cambios en el esquema de forma independiente:
En cada consulta de carga de trabajo, sustituya nyc_taxi.trips_small_inferred por nyc_taxi.trips_small_no_pk y vuelva a ejecutar las tres consultas. El ejemplo original registró los siguientes resultados representativos: Las consultas siguen leyendo el mismo número de filas, pero el esquema optimizado reduce la cantidad de datos representada por esas filas. Por lo tanto, mejoran la duración de las consultas y el uso máximo de memoria sin modificar la selección de datos. Compare el tamaño en disco de las dos tablas:
Para este conjunto de datos, el esquema optimizado reduce el almacenamiento comprimido en aproximadamente un 34 %, de 7,38 GiB a 4,89 GiB.

Optimiza la clave de ordenación

En la familia MergeTree, la clave de ordenación determina cómo se disponen las filas en disco. ClickHouse crea un índice primario disperso a partir de ese orden para omitir los gránulos que no pueden cumplir los filtros de una consulta. A diferencia de una clave primaria en muchas bases de datos transaccionales, no garantiza la unicidad. La clave de ordenación debe reflejar los filtros que utilizan las consultas recurrentes más importantes. El orden de las columnas importa: una clave es más eficaz cuando la consulta filtra por un prefijo útil. Las columnas de menor cardinalidad a veces son eficaces como elementos iniciales cuando se filtran con frecuencia, y un componente temporal suele ser útil para cargas de trabajo basadas en el tiempo. Para obtener orientación detallada sobre cómo elegirla, consulta Elegir una clave primaria. Para este ejemplo, utiliza (passenger_count, pickup_datetime, dropoff_datetime). passenger_count tiene pocos valores distintos y aparece en el filtro por número de pasajeros, mientras que pickup_datetime aparece en la agregación por intervalo de fechas. Aunque pickup_datetime no es la primera columna, ClickHouse puede seguir usando valores de columnas posteriores de la clave para excluir datos cuando la columna inicial no tiene restricciones. Por lo general, filtrar por un prefijo útil de la clave de ordenación permite una poda más eficaz.

Aplicar el cambio de la clave de ordenación

Cree una tabla con el mismo esquema optimizado utilizado en la etapa anterior. Cambie únicamente la clave de ordenación:
En cada consulta de carga de trabajo, sustituye el nombre de la tabla por nyc_taxi.trips_small_pk y vuelve a ejecutar las tres consultas.

Compare los resultados

La guía original registró las siguientes mediciones en las tres etapas: La optimización del esquema reduce el almacenamiento y hace que los valores seleccionados sean menos costosos de procesar. La clave de ordenación aporta la mayor mejora adicional en la agregación por intervalo de fechas, ya que ClickHouse puede omitir los gránulos que quedan fuera del intervalo de fechas. El filtro por número de pasajeros también lee menos filas porque filtra por la primera columna de la clave. El filtro de velocidad calculada sigue leyendo toda la tabla porque se basa en pickup_datetime, dropoff_datetime y trip_distance, en lugar de en un prefijo útil de la clave de ordenación. Inspeccione la agregación por intervalo de fechas con EXPLAIN indexes = 1:
En ClickHouse 25.9 y versiones posteriores, estos ajustes garantizan que EXPLAIN informe de los índices utilizados y de las partes y los gránulos que estos descartan.
El índice primario selecciona 5.061 de 40.167 gránulos. Esta reducción permite que la agregación por intervalo de fechas procese 41,46 millones de filas en lugar de los 329,04 millones totales.

Aplique el método a su carga de trabajo

Siga la misma secuencia para su propia carga de trabajo:
  1. Registre la duración de referencia, las filas y los bytes leídos, y el uso máximo de memoria.
  2. Compruebe si las columnas seleccionadas usan tipos innecesariamente amplios o permisivos.
  3. Aplique y mida los cambios de esquema sin modificar la organización de los datos.
  4. Pruebe una clave de ordenación basada en los filtros utilizados por las consultas recurrentes más importantes.
  5. Compare los datos seleccionados con EXPLAIN indexes = 1 y, a continuación, vuelva a ejecutar las consultas de referencia en condiciones comparables.
No dé por sentado que los tipos o la clave de ordenación de este ejemplo sean adecuados para otro conjunto de datos. Use los valores observados y los filtros de las consultas para tomar esas decisiones.

Próximos pasos

Vuelva a enfoques de optimización para evaluar proyecciones, vistas materializadas, índices de omisión de datos o precálculo si los cambios en el esquema y la clave de ordenación no resuelven el cuello de botella detectado.
Última modificación el 28 de agosto de 2026