¿Qué son las fusiones de partes en ClickHouse?
ClickHouse es rápido no solo para las consultas, sino también para las inserciones, gracias a su capa de almacenamiento, que funciona de forma similar a los árboles LSM: ① Las inserciones (en tablas de la familia del motor MergeTree) crean partes de datos ordenadas e inmutables. ② Todo el procesamiento de los datos se delega a fusiones de partes en segundo plano. Esto hace que las escrituras de datos sean ligeras y muy eficientes. Para controlar el número de partes por tabla e implementar el punto ② anterior, ClickHouse fusiona continuamente (por partición) las partes más pequeñas en otras más grandes en segundo plano hasta que alcanzan un tamaño comprimido aproximado de ~150 GB. El siguiente diagrama ilustra este proceso de fusión en segundo plano:
El
merge level de una parte aumenta en uno con cada fusión adicional. Un nivel de 0 significa que la parte es nueva y aún no se ha fusionado. Las partes que se fusionaron en otras más grandes se marcan como inactivas y, por último, se eliminan tras un tiempo configurable (8 minutos de forma predeterminada). Con el tiempo, esto crea un árbol de partes fusionadas. De ahí el nombre de la tabla merge tree.
Monitorización de las fusiones
handler HTTP /merges, podemos usarlo para visualizar todos los merges de partes de nuestra tabla de ejemplo:
La grabación del dashboard anterior muestra todo el proceso, desde las inserciones iniciales de datos hasta el merge final en una sola parte: ① Número de partes activas. ② Merges de partes, representados visualmente con cuadros (su tamaño refleja el tamaño de la parte). ③ Amplificación de escritura.
Fusiones concurrentes
Cada hilo de fusión ejecuta un bucle: ① Decide qué partes fusionar a continuación y carga esas partes en memoria. ② Fusiona las partes en memoria en una parte más grande. ③ Escribe la parte fusionada en disco. Volver a ① Ten en cuenta que aumentar el número de núcleos de CPU y la cantidad de RAM permite incrementar el rendimiento de las fusiones en segundo plano.
Fusiones con uso de memoria optimizado
Mecánica de las fusiones
La fusión de partes se realiza en varios pasos: ① Descompresión y carga: Los archivos binarios comprimidos de columnas de las partes que se van a fusionar se descomprimen y se cargan en memoria. ② Fusión: Los datos se fusionan en archivos de columnas más grandes. ③ Indexación: Se genera un nuevo índice primario disperso para los archivos de columnas fusionados. ④ Compresión y almacenamiento: Los nuevos archivos de columnas y el índice se comprimen y se guardan en un nuevo directorio que representa la parte de datos fusionada. Los metadatos adicionales de las partes de datos, como índices secundarios de omisión de datos, estadísticas de columnas, sumas de comprobación e índices min-max, también se recrean a partir de los archivos de columnas fusionados. Omitimos estos detalles por simplicidad. La mecánica del paso ② depende del motor MergeTree específico que se utilice, ya que los distintos motores gestionan la fusión de forma diferente. Por ejemplo, las filas pueden agregarse o reemplazarse si están desactualizadas. Como se mencionó antes, este enfoque traslada todo el procesamiento de datos a las fusiones en segundo plano, lo que permite inserciones superrápidas al mantener las operaciones de escritura ligeras y eficientes. A continuación, describiremos brevemente la mecánica de fusión de motores específicos de la familia MergeTree.
Fusiones estándar
La sentencia DDL del diagrama anterior crea una tabla
MergeTree con una clave de ordenación (town, street), lo que significa que los datos en disco se ordenan según estas columnas y que, en consecuencia, se genera un índice primario disperso.
Las columnas de la tabla ① descomprimidas y preordenadas se ② fusionan manteniendo el orden global de clasificación de la tabla definido por su clave de ordenación, ③ se genera un nuevo índice primario disperso y ④ los archivos de columna fusionados y el índice se comprimen y se almacenan como una nueva parte de datos en disco.
Fusiones con reemplazo
La sentencia DDL del diagrama anterior crea una tabla
ReplacingMergeTree con una clave de ordenación (town, street, id), lo que significa que los datos en disco se ordenan según esas columnas y que, en consecuencia, se genera un índice primario disperso.
La ② fusión funciona de forma similar a la de una tabla MergeTree estándar: combina columnas descomprimidas y preordenadas mientras mantiene el orden global de ordenación.
Sin embargo, ReplacingMergeTree elimina las filas duplicadas con la misma clave de ordenación y conserva solo la fila más reciente, según la marca temporal de creación de la parte que la contiene.
Fusiones con suma
La sentencia DDL del diagrama anterior define una tabla
SummingMergeTree con town como clave de ordenación, lo que significa que los datos en disco se ordenan según esta columna y que, en consecuencia, se crea un índice primario disperso.
En el paso ② de fusión, ClickHouse reemplaza todas las filas con la misma clave de ordenación por una sola fila, sumando los valores de las columnas numéricas.
Fusiones con agregación
SummingMergeTree anterior es una variante especializada de la tabla AggregatingMergeTree, que permite la transformación automática e incremental de datos al aplicar cualquiera de las más de 90 funciones de agregación durante las fusiones de partes:
La sentencia DDL del diagrama anterior crea una tabla
AggregatingMergeTree con town como clave de ordenación, lo que garantiza que los datos se ordenen por esta columna en disco y que se genere el índice primario disperso correspondiente.
Durante la fusión ②, ClickHouse sustituye todas las filas con la misma clave de ordenación por una única fila que almacena estados parciales de agregación (por ejemplo, un sum y un count para avg()). Estos estados garantizan resultados precisos mediante fusiones incrementales en segundo plano.