No se recomienda enviar muchos lotes pequeños en modo síncrono, ya que esto provoca la creación de muchas partes. Esto dará lugar a un rendimiento deficiente de las consultas y a errores de “too many part”.
async_insert.
Las inserciones asíncronas son compatibles tanto con las interfaces HTTP como con native TCP.
Cuando están habilitadas (async_insert = 1), las inserciones se almacenan en búfer y solo se escriben en disco una vez que se cumple una de las condiciones de vaciado:
- El búfer alcanza un tamaño de datos especificado (
async_insert_max_data_size, valor predeterminado 100 MiB). - Transcurre un umbral de tiempo (
async_insert_busy_timeout_ms, valor predeterminado 200 ms o 1000 ms en Cloud). - Se acumula un número máximo de consultas de inserción (
async_insert_max_query_number, valor predeterminado 450).
Elegir un modo de retorno
wait_for_async_insert.
Cuando se establece en 1 (el valor predeterminado), ClickHouse solo confirma la inserción después de que los datos se hayan vaciado correctamente en disco. Esto garantiza sólidas garantías de durabilidad y simplifica el manejo de errores: si algo sale mal durante el vaciado, el error se devuelve al cliente. Este modo se recomienda para la mayoría de los escenarios de producción, especialmente cuando los fallos de inserción deben rastrearse de forma fiable.
Los benchmarks muestran que escala bien con la concurrencia, tanto si ejecuta 200 como 500 clientes, gracias a las inserciones adaptativas y a un comportamiento estable en la creación de partes.
Configurar wait_for_async_insert = 0 habilita el modo “fire-and-forget”. En este caso, el servidor confirma la inserción en cuanto los datos se almacenan en el búfer, sin esperar a que lleguen al almacenamiento.
Esto ofrece inserciones de latencia ultrabaja y máximo rendimiento, ideal para datos de alta velocidad y baja criticidad. Sin embargo, esto implica concesiones: no hay garantía de que los datos se persistan, los errores solo aparecen durante el vaciado y no existe una cola dead-letter para las inserciones fallidas; para rastrear fallos es necesario inspeccionar los registros del servidor y las tablas del sistema posteriormente. Use este modo solo si su workload puede tolerar la pérdida de datos.
Los benchmarks también demuestran una reducción sustancial de partes y un menor uso de CPU cuando los vaciados del búfer son poco frecuentes (por ejemplo, cada 30 segundos), pero el riesgo de fallo silencioso sigue presente.
Nuestra recomendación firme es usar async_insert=1,wait_for_async_insert=1 si utiliza inserciones asíncronas. Usar wait_for_async_insert=0 es muy arriesgado porque es posible que su cliente de INSERT no detecte si hay errores, y además puede provocar una posible sobrecarga si su cliente sigue escribiendo rápidamente en una situación en la que el ClickHouse server necesita ralentizar las escrituras y crear cierta contrapresión para garantizar la fiabilidad del service.
Inserciones asíncronas adaptativas
async_insert_use_adaptive_busy_timeout). En lugar de un intervalo de vaciado fijo, el tiempo de espera se ajusta dinámicamente entre un mínimo (async_insert_busy_timeout_min_ms, 50 ms de forma predeterminada) y un máximo (async_insert_busy_timeout_max_ms, 200 ms de forma predeterminada o 1000 ms en Cloud) en función de la tasa de llegada de datos.
Cuando los datos llegan con frecuencia, el tiempo de espera se mantiene más cerca del mínimo para vaciar antes y reducir la latencia de extremo a extremo. Cuando los datos son dispersos, aumenta hacia el máximo para acumular lotes más grandes. Esto resulta especialmente útil en el modo predeterminado (wait_for_async_insert=1), donde un tiempo de espera fijo alto obligaría a los clientes a quedar bloqueados durante todo el intervalo incluso cuando los datos ya están listos para vaciarse.
Manejo de errores
wait_for_async_insert=1), el error se devuelve al cliente. En el modo fire-and-forget, los errores se escriben en los logs del servidor y en la tabla system.asynchronous_inserts.
Cada vaciado crea al menos una parte por cada valor distinto de la clave de partición en el búfer. Incluso en tablas sin clave de partición, un solo vaciado puede producir varias partes si los datos almacenados en el búfer superan max_insert_block_size (valor predeterminado: ~1 millón de filas).
Aunque uses inserciones asíncronas, puedes seguir encontrándote con errores de “too many parts” si la clave de particionamiento tiene una cardinalidad alta.
Deduplicación y fiabilidad
Habilitación de inserciones asíncronas
-
Habilitación de inserciones asíncronas a nivel de usuario. Este ejemplo usa el usuario
default; si crea un usuario distinto, sustituya ese nombre de usuario: -
Puede especificar la configuración de las inserciones asíncronas mediante la cláusula SETTINGS de las consultas de inserción:
-
También puede especificar la configuración de las inserciones asíncronas como parámetros de conexión al usar un cliente de ClickHouse para un lenguaje de programación.
Por ejemplo, así puede hacerlo dentro de una connection string de JDBC cuando usa el JDBC driver de Java de ClickHouse para conectarse a ClickHouse Cloud:
Las inserciones asíncronas no se aplican a las consultas
INSERT INTO ... SELECT. Cuando la inserción contiene una cláusula SELECT, la consulta siempre se ejecuta de forma síncrona, independientemente de la configuración de async_insert.Vaciado de búferes al apagar
Comparación con las tablas Buffer
- No se requieren cambios de DDL. Las inserciones asíncronas son transparentes: se habilita una configuración, no se crean tablas adicionales.
- Búfer por forma. Las inserciones asíncronas mantienen búferes independientes para cada combinación única de forma de consulta y configuración, lo que permite aplicar políticas de vaciado granulares. Las tablas Buffer usan un único búfer por tabla de destino.
- Durabilidad. En el modo predeterminado (
wait_for_async_insert=1), los datos se confirman en disco antes de que el cliente reciba la confirmación. Las tablas Buffer funcionan en modo fire-and-forget: los datos almacenados en el búfer se pierden si se produce un fallo. - Comportamiento del clúster. En los clústeres, los búferes de inserción asíncrona se mantienen por nodo. Las tablas Buffer requieren crearse explícitamente en cada nodo.