ClickHouse se ha implementado como backend para sistemas de BI en tiempo real, demostrando excelente rendimiento en generación de reportes y consultas ad-hoc cuando los datos están correctamente almacenados. A continuación comparto aprendizajes clave tras su implementación con Flink y Kafka.
Integración con MySQL
ClickHouse permite acceder directamente a tablas MySQL mediante motores especializados, evitando duplicación de datos:
-- Crear base de datos enlazada
CREATE DATABASE mysql_db
ENGINE = MySQL('servidor:3306', 'basedatos', 'usuario', 'contraseña');
Ejemplo de consulta cruzada:
SELECT ck.*, mysql.tabla.campo
FROM tabla_clickhouse ck
JOIN mysql_db.tabla_mysql mysql ON ck.id = mysql.id_ref;
Tablas distribuidas con réplica
Implementación correcta requiere dos pasos:
- Tabla local replicada:
CREATE TABLE bd.tabla_nodo ON CLUSTER cluster_default
(
id UInt32,
fecha_evento DateTime,
datos String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/tabla', '{replica}')
PARTITION BY toYYYYMM(fecha_evento)
ORDER BY id;
- Tabla distribuida:
CREATE TABLE bd.tabla_distribuida ON CLUSTER cluster_default
AS bd.tabla_nodo
ENGINE = Distributed(cluster_default, bd, tabla_nodo, rand());
Operaciones DDL requieren sintaxis especial:
-- Actualización
ALTER TABLE bd.tabla_nodo ON CLUSTER cluster_default
UPDATE campo = valor WHERE condición;
-- Eliminación
ALTER TABLE bd.tabla_nodo ON CLUSTER cluster_default
DELETE WHERE condición;
Optimización de escritura
Para máximo rendimiento:
- Buffer de 5-10 segundos
- Lotes de 10,000+ registros
- Evitar acutalizaciones frecuentes
Ejemplo en Flink:
dataStream
.window(TumblingProcessingTimeWindows.of(Time.seconds(5)))
.process(new BatchClickHouseInserter());
Gestión de índices
Los índices secundarios requieren materialización explícita:
-- Añadir índice
ALTER TABLE bd.tabla_nodo ADD INDEX idx_campo(campo) TYPE bloom_filter GRANULARITY 3;
-- Aplicar a datos existentes
ALTER TABLE bd.tabla_nodo MATERIALIZE INDEX idx_campo;
Tipos avanzados
Manejo de estructuras JSON/Map:
CREATE TABLE bd.eventos (
id UUID,
atributos Map(String, String),
metadata_json String
) ENGINE = MergeTree()
ORDER BY id;
-- Consulta de mapas
SELECT atributos['clave'] FROM eventos WHERE id = '...';
-- Extracción JSON
SELECT JSONExtractString(metadata_json, 'ruta') FROM eventos;
Mantenimiento
Optimización manual de tablas ReplacingMergeTree:
OPTIMIZE TABLE bd.tabla_nodo FINAL;
Consulta con desduplicación:
SELECT * FROM bd.tabla_distribuida
FINAL WHERE id = 12345;