ClickHouse 26.x — Columnar Database cho Real-Time Analytics tỷ dòng dữ liệu mỗi giây
Posted on: 4/27/2026 5:11:59 AM
Khi hệ thống cần phân tích hàng tỷ dòng dữ liệu trong vài giây, những database truyền thống như MySQL hay PostgreSQL bắt đầu "nghẹt thở". Đây chính là sân chơi của ClickHouse — columnar database mã nguồn mở chuyên xử lý real-time analytics với tốc độ nhanh gấp hàng trăm lần RDBMS thông thường. Với phiên bản 26.x (2026), ClickHouse tiếp tục nâng tầm với full-text search GA, materialized CTEs, WebAssembly UDFs, và embedded observability stack. Bài viết này đi sâu vào kiến trúc, cách ClickHouse đạt hiệu năng đáng kinh ngạc, và hướng dẫn thiết kế hệ thống analytics production-ready.
1. Tại sao ClickHouse nhanh đến vậy?
ClickHouse được thiết kế từ đầu cho OLAP (Online Analytical Processing) — tối ưu cho các truy vấn đọc trên tập dữ liệu lớn thay vì giao dịch OLTP nhỏ lẻ. Ba trụ cột kiến trúc giúp ClickHouse vượt trội:
1.1. Columnar Storage — Đọc ít, trả nhanh
Khác với row-oriented database (MySQL, PostgreSQL) lưu từng hàng liền nhau trên disk, ClickHouse lưu từng cột riêng biệt. Khi truy vấn SELECT avg(price) FROM orders WHERE date > '2026-01-01', ClickHouse chỉ đọc 2 cột price và date thay vì toàn bộ hàng — giảm I/O lên đến 100x trên bảng rộng.
graph LR
subgraph ROW["Row-Oriented (MySQL)"]
R1["Row 1: id|name|price|date"]
R2["Row 2: id|name|price|date"]
R3["Row 3: id|name|price|date"]
end
subgraph COL["Column-Oriented (ClickHouse)"]
C1["Column: id → 1,2,3,..."]
C2["Column: name → A,B,C,..."]
C3["Column: price → 10,20,30,..."]
C4["Column: date → 01,02,03,..."]
end
Q["SELECT avg(price)
WHERE date > X"] -->|"Đọc toàn bộ rows"| ROW
Q -->|"Chỉ đọc 2 cột"| COL
style COL fill:#f8f9fa,stroke:#4CAF50,color:#2c3e50
style ROW fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style Q fill:#e94560,stroke:#fff,color:#fff
style C3 fill:#e8f5e9,stroke:#4CAF50,color:#2c3e50
style C4 fill:#e8f5e9,stroke:#4CAF50,color:#2c3e50
Hình 1: Row-oriented vs Column-oriented — ClickHouse chỉ đọc các cột cần thiết
1.2. Nén dữ liệu cực hiệu quả
Vì dữ liệu cùng cột có kiểu giống nhau (toàn số, toàn string, toàn date), tỷ lệ nén rất cao. ClickHouse hỗ trợ nhiều codec: LZ4 (mặc định, nhanh), ZSTD (tỷ lệ nén cao hơn), Delta + ZSTD cho time series, và codec mới ALP (v26.3) cho floating-point data. Tỷ lệ nén thực tế thường đạt 5-15x, nghĩa là 1TB dữ liệu gốc chỉ chiếm 70-200GB trên disk.
-- Chọn codec nén phù hợp cho từng cột
CREATE TABLE events (
event_time DateTime CODEC(Delta, ZSTD(3)), -- time series: Delta encoding + ZSTD
user_id UInt64 CODEC(T64, LZ4), -- integer: T64 transform + LZ4
price Float64 CODEC(ALP), -- floating-point: ALP codec (v26.3)
url String CODEC(ZSTD(5)), -- text: ZSTD mức nén cao
status LowCardinality(String) -- dictionary encoding tự động
) ENGINE = MergeTree()
ORDER BY (event_time, user_id);
1.3. Vectorized Query Execution
ClickHouse xử lý dữ liệu theo block (mặc định 65.536 rows/block) thay vì từng row. Mỗi block được xử lý bằng SIMD instructions (SSE4.2, AVX2, AVX-512), tận dụng tối đa CPU pipeline và cache. Kết quả: throughput truy vấn cao gấp 10-100x so với row-by-row processing.
Sparse Primary Index — không như B-Tree
ClickHouse không dùng B-Tree index như RDBMS truyền thống. Thay vào đó, nó dùng sparse index — chỉ lưu giá trị đầu tiên của mỗi granule (mặc định 8.192 rows). Index cực nhỏ (thường vài MB cho bảng hàng tỷ dòng), nên luôn nằm gọn trong RAM. Khi query, ClickHouse skip toàn bộ granules không khớp điều kiện WHERE — gọi là data skipping.
2. ClickHouse 26.x — Những cải tiến đáng chú ý
2.1. Full-Text Search — Cuộc cách mạng tìm kiếm trong ClickHouse
Trước v26.2, tìm kiếm text trong ClickHouse chủ yếu dùng LIKE hoặc Bloom filter index — chậm và không chính xác. Từ v26.2, ClickHouse có full-text index thực sự, dùng front-coding compression và adaptive posting lists tối ưu cho object storage.
-- Tạo full-text index trên cột log message
CREATE TABLE logs (
timestamp DateTime64(3),
service LowCardinality(String),
level Enum8('DEBUG'=0, 'INFO'=1, 'WARN'=2, 'ERROR'=3),
message String,
INDEX idx_msg message TYPE full_text GRANULARITY 1
) ENGINE = MergeTree()
ORDER BY (service, timestamp);
-- Truy vấn full-text nhanh gấp nhiều lần so với LIKE
SELECT timestamp, service, message
FROM logs
WHERE hasToken(message, 'timeout') AND level >= 'ERROR'
ORDER BY timestamp DESC
LIMIT 100;
-- So sánh: Bloom filter quét ~2.400 granules, full-text index chỉ quét ~96 granules
-- trên cùng dataset → nhanh hơn ~25x
Full-text search thay thế Elasticsearch?
Với full-text search GA, ClickHouse bắt đầu lấn sân sang lãnh địa của Elasticsearch trong use case log analytics. Ưu điểm: không cần cluster riêng cho search, dữ liệu nén tốt hơn (5-10x so với Elasticsearch), SQL syntax quen thuộc. Hạn chế: chưa hỗ trợ fuzzy search, relevance scoring phức tạp, hay synonym expansion — các tính năng Elasticsearch đã mature. Kết luận: phù hợp cho log search và structured analytics, chưa thay thế được Elasticsearch cho full-blown search engine.
2.2. Materialized CTEs — Tránh tính toán lặp
Trước v26.3, CTE trong ClickHouse chỉ là syntax sugar — mỗi lần reference đều re-execute. Materialized CTEs lưu kết quả tạm thời và tái sử dụng, đặc biệt hữu ích cho query phức tạp với nhiều sub-aggregation.
-- Materialized CTE: tính một lần, dùng nhiều lần
WITH daily_stats AS MATERIALIZED (
SELECT
toDate(event_time) AS day,
service,
count() AS total_events,
countIf(level = 'ERROR') AS error_count
FROM logs
WHERE event_time >= now() - INTERVAL 30 DAY
GROUP BY day, service
)
SELECT
s1.service,
avg(s1.total_events) AS avg_daily_events,
avg(s1.error_count) AS avg_daily_errors,
-- So sánh với tuần trước
(SELECT avg(total_events) FROM daily_stats s2
WHERE s2.service = s1.service
AND s2.day >= now() - INTERVAL 7 DAY) AS avg_last_7d
FROM daily_stats s1
GROUP BY s1.service;
2.3. WebAssembly UDFs — Custom Functions không giới hạn
ClickHouse 26.3 cho phép viết User-Defined Functions bằng bất kỳ ngôn ngữ nào compile sang WebAssembly — Rust, Go, C++, AssemblyScript. UDF chạy trong an toàn, không ảnh hưởng đến server stability.
// Rust → WebAssembly UDF: tính Haversine distance
// Compile: cargo build --target wasm32-wasi --release
#[no_mangle]
pub extern "C" fn haversine(lat1: f64, lon1: f64, lat2: f64, lon2: f64) -> f64 {
let r = 6371.0; // Earth radius in km
let dlat = (lat2 - lat1).to_radians();
let dlon = (lon2 - lon1).to_radians();
let a = (dlat / 2.0).sin().powi(2)
+ lat1.to_radians().cos() * lat2.to_radians().cos()
* (dlon / 2.0).sin().powi(2);
r * 2.0 * a.sqrt().atan2((1.0 - a).sqrt())
}
-- Đăng ký Wasm UDF trong ClickHouse
CREATE FUNCTION haversine_km AS 'haversine'
USING '/path/to/haversine.wasm'
ARGUMENTS (lat1 Float64, lon1 Float64, lat2 Float64, lon2 Float64)
RETURNS Float64;
-- Sử dụng: tìm tất cả cửa hàng trong bán kính 5km
SELECT name, haversine_km(10.7769, 106.7009, lat, lon) AS distance_km
FROM stores
WHERE distance_km <= 5
ORDER BY distance_km;
3. Thiết kế hệ thống Analytics với ClickHouse
Dưới đây là kiến trúc reference cho hệ thống analytics production xử lý hàng triệu events/giây:
graph TB
SOURCE["Data Sources
(Apps, IoT, Logs)"] --> KAFKA["Apache Kafka
/ Redpanda"]
KAFKA --> CH_KAFKA["Kafka Engine Table
(ClickHouse)"]
CH_KAFKA --> MV["Materialized View
(Transform + Aggregate)"]
MV --> TARGET["MergeTree Table
(Final Storage)"]
TARGET --> QUERY["Query Layer"]
QUERY --> GRAFANA["Grafana
Dashboard"]
QUERY --> API["Analytics API
(.NET / Node.js)"]
QUERY --> AGENT["AI Agent
(MCP Server)"]
SOURCE --> BATCH["Batch Ingestion
(Airflow / dbt)"]
BATCH --> TARGET
style TARGET fill:#e94560,stroke:#fff,color:#fff
style KAFKA fill:#2c3e50,stroke:#e94560,color:#fff
style MV fill:#16213e,stroke:#e94560,color:#fff
style GRAFANA fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style API fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style AGENT fill:#f8f9fa,stroke:#e94560,color:#2c3e50
Hình 2: Kiến trúc analytics pipeline — streaming qua Kafka + batch, lưu trữ MergeTree, phục vụ dashboard + API + AI agent
3.1. MergeTree Engine — Trái tim của ClickHouse
MergeTree là table engine quan trọng nhất. Dữ liệu insert được ghi vào parts riêng biệt (immutable), sau đó ClickHouse merge các parts nhỏ thành parts lớn hơn ở background — tương tự LSM-tree. Thiết kế này cho phép insert cực nhanh (append-only) và query hiệu quả (parts lớn, sorted).
-- Thiết kế bảng analytics events tối ưu
CREATE TABLE analytics_events (
-- Partition key: theo tháng, giúp TTL và query pruning
event_date Date,
event_time DateTime64(3),
-- Primary key columns: thứ tự quan trọng!
-- Đặt cột filter phổ biến nhất lên đầu
tenant_id UInt32,
event_type LowCardinality(String),
user_id UInt64,
-- Payload
properties String CODEC(ZSTD(3)),
revenue Decimal64(2) CODEC(Delta, ZSTD),
country LowCardinality(String),
device LowCardinality(String),
-- Full-text search trên description
description String,
INDEX idx_desc description TYPE full_text GRANULARITY 1
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date)
ORDER BY (tenant_id, event_type, event_time, user_id)
TTL event_date + INTERVAL 90 DAY DELETE
SETTINGS
index_granularity = 8192,
min_bytes_for_wide_part = 10485760;
Nguyên tắc chọn ORDER BY
ORDER BY trong ClickHouse không chỉ sắp xếp — nó quyết định cấu trúc primary index và hiệu quả data skipping. Quy tắc: đặt cột có cardinality thấp nhất lên đầu (tenant_id, event_type), rồi mới đến cột cardinality cao (user_id). Cột time nên ở giữa nếu bạn thường query theo time range kết hợp filter khác. Sai ORDER BY có thể khiến query chậm gấp 100x trên cùng dataset.
3.2. Materialized Views — Tính toán trước, truy vấn tức thì
Materialized Views trong ClickHouse hoạt động như trigger: mỗi khi dữ liệu insert vào bảng nguồn, MV tự động transform và ghi vào bảng đích. Đây là cơ chế cốt lõi cho real-time aggregation.
-- Bảng đích cho aggregated metrics
CREATE TABLE hourly_metrics (
hour DateTime,
tenant_id UInt32,
event_type LowCardinality(String),
event_count AggregateFunction(count, UInt64),
unique_users AggregateFunction(uniq, UInt64),
total_revenue AggregateFunction(sum, Decimal64(2))
)
ENGINE = AggregatingMergeTree()
ORDER BY (tenant_id, event_type, hour);
-- Materialized View: auto-aggregate khi insert
CREATE MATERIALIZED VIEW mv_hourly_metrics
TO hourly_metrics AS
SELECT
toStartOfHour(event_time) AS hour,
tenant_id,
event_type,
countState() AS event_count,
uniqState(user_id) AS unique_users,
sumState(revenue) AS total_revenue
FROM analytics_events
GROUP BY hour, tenant_id, event_type;
-- Query: merge kết quả aggregate (sub-millisecond trên pre-aggregated data)
SELECT
hour,
countMerge(event_count) AS events,
uniqMerge(unique_users) AS users,
sumMerge(total_revenue) AS revenue
FROM hourly_metrics
WHERE tenant_id = 42
AND hour >= now() - INTERVAL 24 HOUR
GROUP BY hour
ORDER BY hour;
3.3. Streaming Ingestion từ Kafka
ClickHouse có Kafka table engine built-in, cho phép consume trực tiếp từ Kafka topic mà không cần connector bên ngoài:
-- Kafka source table
CREATE TABLE kafka_events (
event_time DateTime64(3),
tenant_id UInt32,
event_type String,
user_id UInt64,
properties String,
revenue Decimal64(2)
)
ENGINE = Kafka()
SETTINGS
kafka_broker_list = 'kafka-1:9092,kafka-2:9092,kafka-3:9092',
kafka_topic_list = 'analytics-events',
kafka_group_name = 'clickhouse-consumer',
kafka_format = 'JSONEachRow',
kafka_num_consumers = 4,
-- v26.2: time-based flushing thay vì chờ đủ rows
kafka_flush_interval_ms = 5000;
-- Pipe từ Kafka → MergeTree qua Materialized View
CREATE MATERIALIZED VIEW mv_kafka_to_events
TO analytics_events AS
SELECT
event_time,
toDate(event_time) AS event_date,
tenant_id,
event_type,
user_id,
properties,
revenue,
JSONExtractString(properties, 'country') AS country,
JSONExtractString(properties, 'device') AS device,
'' AS description
FROM kafka_events;
4. ClickHouse so với các giải pháp khác
| Tiêu chí | ClickHouse | Elasticsearch | Apache Druid | BigQuery |
|---|---|---|---|---|
| Mô hình | Columnar OLAP | Inverted Index | Columnar OLAP | Serverless OLAP |
| Nén dữ liệu | 5-15x (rất tốt) | 1.5-3x | 3-8x | Managed |
| Query latency | Sub-second | Sub-second | Sub-second | Seconds |
| Ingestion | Triệu rows/sec | Trăm nghìn docs/sec | Triệu rows/sec | Streaming (limited) |
| SQL support | Full SQL + extensions | Có (limited) | Có (Druid SQL) | Full SQL |
| Full-text search | GA (v26.2) | Native, mature | Không | Limited |
| JOIN performance | Tốt (v26.2+) | Rất hạn chế | Hạn chế | Tốt |
| Chi phí vận hành | Thấp (self-host) / Medium (Cloud) | Cao (RAM-hungry) | Cao (complex ops) | Pay-per-query |
| Phù hợp nhất | Analytics, observability, time series | Search, logging | Real-time dashboards | Ad-hoc analytics |
5. Case Study thực tế 2026
5.1. Cloudflare — 1.61 Quadrillion Events/Ngày
Cloudflare sử dụng ClickHouse để xử lý 1.61 quadrillion events mỗi ngày (1.61 × 10¹⁵) trên hơn 300 data center toàn cầu. Một single query có thể quét 96 nghìn tỷ events trong dưới 2 giây. Kiến trúc: mỗi data center có local ClickHouse cluster, query được fan-out/merge qua distributed layer.
5.2. Goldsky — Blockchain Analytics 12x nhanh hơn
Goldsky (blockchain data infrastructure) chuyển từ pipeline Kafka/Avro sang đọc trực tiếp ClickHouse với Apache Arrow format, đạt 12x speedup cho historical backfill — từ 50K lên 600K rows/sec. Bí quyết: tận dụng columnar-to-columnar transfer (ClickHouse → Arrow) không cần serialize/deserialize từng row.
5.3. Hookdeck — Search latency từ 30s xuống 400ms
Hookdeck (webhook infrastructure) cần tìm kiếm trong hàng tỷ webhook payload. Trước ClickHouse: truy vấn full-text mất 30+ giây. Sau khi chuyển sang ClickHouse với kỹ thuật hash payload values vào typed bucket columns + iterative time-window scanning: latency giảm xuống dưới 400ms — nhanh hơn 60x.
6. Best Practices cho Production
6.1. Schema Design
Những sai lầm phổ biến
1. Dùng UUID làm primary key: UUID phân tán ngẫu nhiên → data skipping gần như vô dụng. Thay bằng composite key với cột cardinality thấp đứng trước.
2. Quá nhiều cột nhỏ: ClickHouse mở file descriptor cho mỗi cột × mỗi part. Bảng 500+ cột với nhiều parts gây overhead lớn. Gộp các trường liên quan vào Nested hoặc JSON.
3. INSERT từng row: Mỗi INSERT tạo một part mới → merge pressure khổng lồ. Luôn batch (tối thiểu 1.000 rows/batch, lý tưởng 10K-100K).
4. Thiếu TTL: Dữ liệu analytics tăng nhanh. Luôn set TTL theo retention policy để tự động xóa dữ liệu cũ.
6.2. Performance Tuning
-- Kiểm tra compression ratio
SELECT
table,
formatReadableSize(sum(data_compressed_bytes)) AS compressed,
formatReadableSize(sum(data_uncompressed_bytes)) AS uncompressed,
round(sum(data_uncompressed_bytes) / sum(data_compressed_bytes), 2) AS ratio
FROM system.columns
WHERE database = 'analytics'
GROUP BY table
ORDER BY sum(data_uncompressed_bytes) DESC;
-- Kiểm tra query đang quét bao nhiêu granules
SELECT
query,
read_rows,
read_bytes,
result_rows,
formatReadableSize(memory_usage) AS peak_memory,
query_duration_ms
FROM system.query_log
WHERE type = 'QueryFinish'
AND query_duration_ms > 1000
ORDER BY query_duration_ms DESC
LIMIT 10;
-- Async insert (mặc định từ v26.3)
-- ClickHouse tự gom batch insert nhỏ thành batch lớn
SET async_insert = 1;
SET wait_for_async_insert = 0; -- không chờ, fire-and-forget
6.3. clickhousectl — CLI mới cho thời đại Agent
ClickHouse vừa ra mắt clickhousectl (beta, 04/2026) — CLI chính thức hợp nhất quản lý local installation và cloud deployment. Điểm đặc biệt: thiết kế sẵn cho AI agent integration qua MCP server, cho phép AI agent truy vấn và quản lý ClickHouse cluster thông qua giao thức chuẩn.
# Cài đặt clickhousectl
curl -fsSL https://clickhouse.com/install-ctl | bash
# Quản lý local instance
clickhousectl install 26.3 # Cài phiên bản cụ thể
clickhousectl start # Khởi động server
clickhousectl status # Kiểm tra trạng thái
# Kết nối cloud
clickhousectl cloud login
clickhousectl cloud services # Liệt kê cloud services
clickhousectl cloud query "SELECT count() FROM analytics_events"
# Scaffolding project mới
clickhousectl init my-analytics # Tạo project template
7. Kết luận
ClickHouse đã chứng minh vị thế là database nhanh nhất cho real-time analytics ở quy mô từ startup đến Cloudflare (1.61 quadrillion events/ngày). Với phiên bản 26.x, ClickHouse không chỉ nhanh hơn mà còn thông minh hơn — full-text search GA loại bỏ nhu cầu Elasticsearch cho log analytics, materialized CTEs đơn giản hoá query phức tạp, WebAssembly UDFs mở rộng khả năng xử lý không giới hạn, và clickhousectl + MCP server chuẩn bị sẵn cho kỷ nguyên agentic AI.
Nếu hệ thống của bạn cần phân tích hàng tỷ dòng dữ liệu với latency dưới giây — cho dù là observability, product analytics, hay IoT time series — ClickHouse xứng đáng nằm trong shortlist đánh giá. Kết hợp với Kafka cho streaming ingestion, Materialized Views cho real-time aggregation, và Grafana cho visualization, bạn có một analytics stack hoàn chỉnh với chi phí vận hành thấp hơn đáng kể so với Elasticsearch hay các managed service đắt đỏ.
Nguồn tham khảo
- ClickHouse April 2026 Newsletter — clickhouse.com
- ClickHouse March 2026 Newsletter — clickhouse.com
- How to Choose a Database for Real-Time Analytics in 2026 — clickhouse.com
- Real-Time Analytics Platforms: A Practical Comparison — clickhouse.com
- ClickHouse Expands Strategic Collaboration with Google Cloud — FinancialContent
- ClickHouse Builds a CLI to Make Its Databases Agent-Native — Futurum Group
- ClickHouse 26.2 Release Highlights — TipRanks
Core Web Vitals 2026 — Tối ưu LCP, INP và CLS để website nhanh hơn
Cloudflare Pages — Deploy Full-Stack miễn phí trên Edge toàn cầu
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.