Saltar al contenido principal
Las actualizaciones ligeras se encuentran actualmente en fase beta. Si tienes algún problema, abre una incidencia en el repositorio de ClickHouse.
La sentencia de actualización ligera UPDATE actualiza las filas de una tabla [db.]table que coinciden con la expresión filter_expr. Se denomina “actualización ligera” para diferenciarla de la consulta ALTER TABLE ... UPDATE, que es un proceso costoso que reescribe columnas completas en las partes de datos. Solo está disponible para la familia de motores de tabla MergeTree.
UPDATE [db.]table [ON CLUSTER cluster] SET column1 = expr1 [, ...] [IN PARTITION partition_expr] WHERE filter_expr;
filter_expr debe ser de tipo UInt8. Esta consulta actualiza los valores de las columnas especificadas con los valores de las expresiones correspondientes en las filas en las que filter_expr toma un valor distinto de cero. Los valores se convierten al tipo de la columna mediante el operador CAST. No se admite la actualización de columnas utilizadas en el cálculo de las claves primarias o de partición.

Ejemplos

UPDATE hits SET Title = 'Updated Title' WHERE EventDate = today();

UPDATE wikistat SET hits = hits + 1, time = now() WHERE path = 'ClickHouse';

Las actualizaciones ligeras no actualizan los datos inmediatamente

La actualización ligera UPDATE se implementa mediante partes de parche, un tipo especial de parte de datos que contiene solo las columnas y filas actualizadas. Una actualización ligera UPDATE crea partes de parche, pero no modifica físicamente de inmediato los datos originales en el almacenamiento. El proceso de actualización es similar al de una consulta INSERT ... SELECT ..., pero la consulta UPDATE espera a que se complete la creación de la parte de parche antes de devolver el control. Los valores actualizados quedan:
  • Inmediatamente visibles en las consultas SELECT mediante la aplicación de parches
  • Materializados físicamente solo durante fusiones y mutaciones posteriores
  • Eliminados automáticamente una vez que todas las partes activas tienen los parches materializados

Requisitos de las actualizaciones ligeras

Las actualizaciones ligeras son compatibles con los motores MergeTree, ReplacingMergeTree, CollapsingMergeTree y VersionedCollapsingMergeTree, así como con sus versiones Replicated y Shared. Para usar actualizaciones ligeras, la materialización de las columnas _block_number y _block_offset debe habilitarse mediante las opciones de configuración de la tabla enable_block_number_column y enable_block_offset_column.

Eliminaciones ligeras

Una consulta de eliminación ligera DELETE puede ejecutarse como una actualización ligera UPDATE en lugar de una mutación ALTER UPDATE. La implementación de la eliminación ligera DELETE se controla mediante el ajuste lightweight_delete_mode.

Consideraciones de rendimiento

Ventajas de las actualizaciones ligeras:
  • La latencia de la actualización es comparable a la de la consulta INSERT ... SELECT ...
  • Solo se escriben las columnas y los valores actualizados, no columnas completas en las partes de datos
  • No es necesario esperar a que terminen las fusiones o mutaciones en ejecución; por lo tanto, la latencia de una actualización es predecible
  • Es posible ejecutar actualizaciones ligeras en paralelo
Posibles impactos en el rendimiento:
  • Añaden una sobrecarga a las consultas SELECT que necesitan aplicar parches
  • Los índices de omisión no se usarán para las columnas de partes de datos que tengan parches pendientes de aplicar. Las proyecciones no se usarán si la tabla tiene partes de parche, incluso en las partes de datos que no tengan parches pendientes de aplicar.
  • Las actualizaciones pequeñas demasiado frecuentes pueden provocar un error “Too many parts”. Se recomienda agrupar varias actualizaciones en una sola consulta, por ejemplo, incluyendo los ID de las actualizaciones en una sola cláusula IN dentro de la cláusula WHERE
  • Las actualizaciones ligeras están diseñadas para actualizar pequeñas cantidades de filas (hasta aproximadamente el 10 % de la tabla). Si necesita actualizar una cantidad mayor, se recomienda usar la mutación ALTER TABLE ... UPDATE

Operaciones concurrentes

Las actualizaciones ligeras, a diferencia de las mutaciones tradicionales, no esperan a que finalicen las fusiones/mutaciones que están en ejecución. La consistencia de las actualizaciones ligeras concurrentes se controla mediante la configuración update_sequential_consistency y update_parallel_mode.

Actualizar permisos

UPDATE requiere el privilegio ALTER UPDATE. Para habilitar las sentencias UPDATE en una tabla específica para un usuario concreto, ejecute:
GRANT ALTER UPDATE ON db.table TO username;

Detalles de la implementación

Las partes de parche son iguales que las partes normales, pero contienen solo las columnas actualizadas y varias columnas del sistema:
  • _part - el nombre de la parte original
  • _part_offset - el número de fila en la parte original
  • _block_number - el número de bloque de la fila en la parte original
  • _block_offset - el desplazamiento del bloque de la fila en la parte original
  • _data_version - la versión de los datos actualizados (número de bloque asignado a la consulta UPDATE)
En promedio, esto añade unos 40 bytes (datos sin comprimir) de sobrecarga por cada fila actualizada en las partes de parche. Las columnas del sistema ayudan a localizar las filas de la parte original que deben actualizarse. Las columnas del sistema están relacionadas con las columnas virtuales de la parte original, que se añaden durante la lectura si deben aplicarse partes de parche. Las partes de parche se ordenan por _part y _part_offset. Las partes de parche pertenecen a particiones distintas de la parte original. El ID de partición de la parte de parche es patch-<hash of column names in patch part>-<original_partition_id>. Por lo tanto, las partes de parche con columnas diferentes se almacenan en particiones distintas. Por ejemplo, tres actualizaciones SET x = 1 WHERE <cond>, SET y = 1 WHERE <cond> y SET x = 1, y = 1 WHERE <cond> crearán tres partes de parche en tres particiones distintas. Las partes de parche pueden fusionarse entre sí para reducir la cantidad de parches aplicados en las consultas SELECT y disminuir la sobrecarga. La fusión de partes de parche usa el algoritmo de fusión replacing con _data_version como columna de versión. Por lo tanto, las partes de parche siempre almacenan la versión más reciente de cada fila actualizada de la parte. Las actualizaciones ligeras no esperan a que terminen las fusiones y mutaciones que se estén ejecutando en ese momento, y siempre usan una instantánea actual de las partes de datos para ejecutar una actualización y generar una parte de parche. Por eso, puede haber dos casos al aplicar partes de parche. Por ejemplo, si leemos la parte A, necesitamos aplicar la parte de parche X:
  • si X contiene la propia parte A. Esto ocurre si A no estaba participando en una fusión cuando se ejecutó UPDATE.
  • si X contiene las partes B y C, que están cubiertas por la parte A. Esto ocurre si había una fusión (B, C) -> A en ejecución cuando se ejecutó UPDATE.
Para estos dos casos, respectivamente, hay dos formas de aplicar partes de parche:
  • Usar una fusión por las columnas ordenadas _part, _part_offset.
  • Usar join por las columnas _block_number, _block_offset.
El modo join es más lento y requiere más memoria que el modo de fusión, pero se usa con menos frecuencia.
  • ALTER UPDATE - Operaciones UPDATE de alto costo
  • eliminación ligera - Operaciones de eliminación ligera con DELETE
  • APPLY PATCHES - Forzar la materialización física de los parches en las partes de datos (operación de mutación)
Última modificación el 10 de junio de 2026