ClickHouse es una base de datos columnar de código abierto diseñada para consultas analíticas (OLAP): agrega miles de millones de filas en segundos y comprime los datos de forma muy eficiente. Se usa para analítica de eventos, logs, métricas y cuadros de mando en tiempo real. En este tutorial instalarás ClickHouse en Ubuntu 24.04 desde el repositorio oficial, crearás un usuario y una tabla MergeTree, cargarás datos de prueba y definirás una vista materializada que mantiene agregados diarios de forma automática.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS de 64 bits (x86_64 o arm64), por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Al menos 4 GB de RAM. ClickHouse funciona con menos, pero las agregaciones grandes consumen memoria.
- UFW activo si vas a permitir conexiones remotas.
Paso 1: Añadir el repositorio oficial de ClickHouse
Los paquetes de Ubuntu no incluyen ClickHouse, así que usarás el repositorio oficial de packages.clickhouse.com. Instala las dependencias:
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl gnupg
Descarga la clave de firma en /etc/apt/keyrings y añade el repositorio del canal stable:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | sudo gpg --dearmor -o /etc/apt/keyrings/clickhouse-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/clickhouse-keyring.gpg arch=$(dpkg --print-architecture)] https://packages.clickhouse.com/deb stable main" | sudo tee /etc/apt/sources.list.d/clickhouse.list
Actualiza el índice de paquetes:
sudo apt update
Notasi prefieres versiones con soporte extendido, sustituye
stableporltsen la línea del repositorio.
Paso 2: Instalar y arrancar ClickHouse
Instala el servidor y el cliente:
sudo apt install -y clickhouse-server clickhouse-client
Durante la instalación se te pedirá una contraseña para el usuario default. Escribe una contraseña robusta; la usarás enseguida. El instalador la guarda como hash en /etc/clickhouse-server/users.d/default-password.xml.
Habilita y arranca el servicio:
sudo systemctl enable --now clickhouse-server
Comprueba que está activo:
systemctl status clickhouse-server --no-pager
● clickhouse-server.service - ClickHouse Server (analytic DBMS for big data)
Loaded: loaded (/usr/lib/systemd/system/clickhouse-server.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-25 10:02:14 UTC; 5s ago
Conéctate con el cliente y lanza una consulta de prueba:
clickhouse-client --password --query "SELECT version()"
Password for user (default):
25.8.4.13
Por defecto, ClickHouse solo escucha en localhost (puerto 8123 para HTTP y 9000 para el protocolo nativo), así que todavía no es accesible desde fuera.
Paso 3: Habilitar la gestión de usuarios con SQL
Es mejor no usar default desde las aplicaciones. Para crear usuarios con CREATE USER, el usuario default necesita el permiso access_management. Actívalo con un archivo de configuración propio en users.d, que ClickHouse fusiona con la configuración principal y que no se sobrescribe al actualizar:
sudo nano /etc/clickhouse-server/users.d/access-management.xml
<clickhouse>
<users>
<default>
<access_management>1</access_management>
</default>
</users>
</clickhouse>
Los cambios en users.d se recargan automáticamente en unos segundos. Abre una sesión interactiva:
clickhouse-client --password
Crea la base de datos y un usuario para la aplicación con permisos solo sobre ella. Sustituye your_strong_password:
CREATE DATABASE IF NOT EXISTS analytics;
CREATE USER analytics_user IDENTIFIED WITH sha256_password BY 'your_strong_password';
GRANT SELECT, INSERT, CREATE TABLE, CREATE VIEW, ALTER, DROP TABLE, DROP VIEW ON analytics.* TO analytics_user;
Sal con exit y conéctate con el nuevo usuario para comprobarlo:
clickhouse-client --user analytics_user --password --query "SHOW DATABASES"
Password for user (analytics_user):
analytics
A partir de aquí, las sentencias SQL se ejecutan con clickhouse-client --user analytics_user --password.
Paso 4: Crear una tabla MergeTree
La familia MergeTree es la base de casi todas las tablas de ClickHouse. Guarda los datos ordenados por la clave ORDER BY, que actúa como índice disperso: elige las columnas por las que más filtras, de menor a mayor cardinalidad. PARTITION BY agrupa los datos por mes para poder borrar o mover periodos completos, y TTL elimina automáticamente las filas antiguas.
CREATE TABLE analytics.events
(
event_time DateTime,
event_type LowCardinality(String),
user_id UInt64,
country LowCardinality(String),
value Float64
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_time)
ORDER BY (event_type, event_time)
TTL event_time + INTERVAL 1 YEAR;
LowCardinality(String) codifica en diccionario columnas con pocos valores distintos, lo que reduce espacio y acelera los filtros.
Otros motores de la familia que conviene conocer:
| Motor | Uso |
|---|---|
MergeTree | Eventos y logs de solo inserción |
ReplacingMergeTree | Deduplicar filas con la misma clave, quedándose con la versión más reciente |
SummingMergeTree | Sumar columnas numéricas de filas con la misma clave al fusionar partes |
AggregatingMergeTree | Guardar estados de funciones de agregación (medias, únicos, percentiles) |
Paso 5: Cargar datos
Genera un millón de eventos de prueba repartidos en los últimos 30 días con la función de tabla numbers():
INSERT INTO analytics.events
SELECT
now() - (rand() % 2592000) AS event_time,
['page_view', 'click', 'signup', 'purchase'][rand() % 4 + 1] AS event_type,
rand() % 50000 AS user_id,
['ES', 'MX', 'AR', 'US', 'DE'][rand() % 5 + 1] AS country,
round(randUniform(1, 200), 2) AS value
FROM numbers(1000000);
Para cargar un archivo CSV desde la shell, pasa el archivo por la entrada estándar indicando el formato. Crea un archivo de ejemplo:
nano ~/events.csv
2026-09-25 10:00:00,purchase,101,ES,59.90
2026-09-25 10:01:30,click,102,MX,0
Cárgalo:
clickhouse-client --user analytics_user --password --query "INSERT INTO analytics.events FORMAT CSV" < ~/events.csv
También puedes insertar por la interfaz HTTP del puerto 8123, útil desde scripts o agentes de recogida de datos. Este ejemplo envía una fila en formato JSONEachRow:
echo '{"event_time":"2026-09-25 10:05:00","event_type":"signup","user_id":103,"country":"AR","value":0}' | \
curl -sS -u analytics_user:your_strong_password \
'http://localhost:8123/?query=INSERT%20INTO%20analytics.events%20FORMAT%20JSONEachRow' --data-binary @-
Comprueba el número de filas:
clickhouse-client --user analytics_user --password --query "SELECT count() FROM analytics.events"
1000003
Paso 6: Ejecutar consultas analíticas
Las consultas de agregación son donde ClickHouse destaca. Ingresos por día y país durante la última semana:
SELECT
toDate(event_time) AS day,
country,
count() AS purchases,
round(sum(value), 2) AS revenue
FROM analytics.events
WHERE event_type = 'purchase'
AND event_time >= now() - INTERVAL 7 DAY
GROUP BY day, country
ORDER BY day DESC, revenue DESC
LIMIT 10;
Usuarios únicos aproximados y percentiles del valor por tipo de evento:
SELECT
event_type,
uniq(user_id) AS usuarios,
quantiles(0.5, 0.95, 0.99)(value) AS p50_p95_p99
FROM analytics.events
GROUP BY event_type;
uniq() es una estimación muy precisa y mucho más rápida que count(DISTINCT ...). Al final de cada consulta, el cliente muestra las filas leídas y el tiempo:
4 rows in set. Elapsed: 0.041 sec. Processed 1.00 million rows, 13.00 MB (24.39 million rows/s., 317.07 MB/s.)
Para ver si una consulta aprovecha la clave de ordenación, usa EXPLAIN indexes = 1:
EXPLAIN indexes = 1
SELECT count() FROM analytics.events WHERE event_type = 'purchase';
En la salida, la sección PrimaryKey indica cuántos gránulos se leen frente al total. Si filtras por event_type, solo se lee una parte de la tabla.
Paso 7: Crear una vista materializada
Una vista materializada en ClickHouse funciona como un disparador de inserción: cada bloque que llega a la tabla origen se transforma y se escribe en una tabla destino. Así mantienes resúmenes precalculados sin procesos externos.
Crea la tabla destino con SummingMergeTree, que suma events y revenue de las filas con la misma clave cuando fusiona partes:
CREATE TABLE analytics.daily_stats
(
day Date,
event_type LowCardinality(String),
events UInt64,
revenue Float64
)
ENGINE = SummingMergeTree
ORDER BY (day, event_type);
Crea la vista que la alimenta:
CREATE MATERIALIZED VIEW analytics.daily_stats_mv TO analytics.daily_stats AS
SELECT
toDate(event_time) AS day,
event_type,
count() AS events,
sum(value) AS revenue
FROM analytics.events
GROUP BY day, event_type;
La vista solo procesa inserciones nuevas. Rellena el histórico una vez con un INSERT ... SELECT:
INSERT INTO analytics.daily_stats
SELECT toDate(event_time), event_type, count(), sum(value)
FROM analytics.events
GROUP BY toDate(event_time), event_type;
Como las fusiones son asíncronas, consulta siempre la tabla destino agregando de nuevo con sum():
SELECT day, event_type, sum(events) AS events, round(sum(revenue), 2) AS revenue
FROM analytics.daily_stats
WHERE day >= today() - 2
GROUP BY day, event_type
ORDER BY day DESC, event_type;
Inserta un evento más en analytics.events y repite la consulta: el contador del día de hoy aumentará sin ninguna acción adicional.
Paso 8: Revisar almacenamiento y compresión
La tabla del sistema system.parts muestra cuánto ocupa cada tabla antes y después de comprimir:
SELECT
table,
formatReadableSize(sum(data_compressed_bytes)) AS comprimido,
formatReadableSize(sum(data_uncompressed_bytes)) AS sin_comprimir,
count() AS partes
FROM system.parts
WHERE active AND database = 'analytics'
GROUP BY table;
table comprimido sin_comprimir partes
events 9.12 MiB 22.89 MiB 4
daily_stats 1.35 KiB 2.51 KiB 2
Para localizar consultas lentas, revisa system.query_log:
SELECT event_time, query_duration_ms, read_rows, substring(query, 1, 80) AS query
FROM system.query_log
WHERE type = 'QueryFinish' AND query_duration_ms > 1000
ORDER BY event_time DESC
LIMIT 10;
Paso 9: Permitir conexiones remotas (opcional)
Si tu aplicación o Grafana están en otro servidor, haz que ClickHouse escuche en todas las interfaces con un archivo en config.d:
sudo nano /etc/clickhouse-server/config.d/listen.xml
<clickhouse>
<listen_host>0.0.0.0</listen_host>
</clickhouse>
Reinicia el servicio, ya que el cambio de escucha no se aplica en caliente:
sudo systemctl restart clickhouse-server
Abre los puertos solo para la IP de tu aplicación, sustituyendo your_app_ip:
sudo ufw allow from your_app_ip to any port 8123 proto tcp
sudo ufw allow from your_app_ip to any port 9000 proto tcp
Advertenciano expongas los puertos 8123 y 9000 a todo Internet. Si necesitas acceso público, configura TLS en ClickHouse o pon delante un proxy con HTTPS.
Solución de problemas
Authentication failed: password is incorrect: comprueba el usuario con--user. Si olvidaste la contraseña dedefault, edita/etc/clickhouse-server/users.d/default-password.xmly define una nueva.Not enough privilegesal crear usuarios: el archivoaccess-management.xmlno se ha cargado. Revisa su sintaxis y el log/var/log/clickhouse-server/clickhouse-server.err.log.Too many parts: estás insertando fila a fila. Agrupa las inserciones en lotes de miles de filas o activaasync_insert=1en la conexión del cliente.- El servicio no arranca: consulta
sudo journalctl -u clickhouse-server -n 50y el log de errores anterior; suele deberse a un XML mal formado enconfig.dousers.d.
Conclusión
Has instalado ClickHouse en Ubuntu 24.04 desde el repositorio oficial, has creado un usuario dedicado, una tabla MergeTree con partición y TTL, y una vista materializada que mantiene estadísticas diarias automáticamente. Con este esquema puedes empezar a ingerir eventos reales y consultarlos en milisegundos.
Como siguientes pasos, puedes:
- Conectar Grafana con el plugin oficial de ClickHouse para crear paneles.
- Enviar logs con Vector o Fluent Bit directamente a la interfaz HTTP.
- Planificar copias de seguridad con el comando
BACKUPde ClickHouse hacia un disco local o un bucket S3 configurado como destino de backups.
