Introduction
The Architecture of ClickHouse MergeTree Engines
Designing the Schema for Access Log Ingestion
CREATE TABLE default.http_access_logs (
event_date Date,
event_time DateTime,
client_ip String,
http_method LowCardinality(String),
request_uri String,
status_code UInt16,
bytes_sent UInt64,
request_time_ms Float32,
user_agent String
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_date)
ORDER BY (http_method, status_code, event_date, event_time)
SETTINGS index_granularity = 8192;- LowCardinality: Fields with limited distinct values such as HTTP methods ('GET', 'POST', 'PUT') are wrapped in 'LowCardinality(String)' to compress data dictionary representations in memory.
- Partitioning: Partitioning by month via 'toYYYYMM(event_date)' allows ClickHouse to drop entire data directories instantly during data retention purges without executing expensive row-level delete statements.
- Primary Key Ordering: Ordering columns from lowest cardinality to highest cardinality maximizes sparse index effectiveness and data compression ratios.
Optimizing Asynchronous Inserts for Extreme Throughput
Enabling Asynchronous Inserts Globally
<profiles>
<default>
<async_insert>1</async_insert>
<async_insert_threads>4</async_insert_threads>
<async_insert_max_data_size>10000000</async_insert_max_data_size>
<async_insert_busy_timeout_ms>1000</async_insert_busy_timeout_ms>
</default>
</profiles>| Setting Parameter | Recommended Production Value | Description |
|---|---|---|
| 'async_insert' | '1' | Globally enables asynchronous buffering for client insert queries. |
| 'async_insert_max_data_size' | '10000000' (10MB) | Maximum uncompressed data size accumulated before triggering a forced flush. |
| 'async_insert_busy_timeout_ms' | '1000' (1s) | Maximum time window data stays in memory before being written to disk. |
| 'async_insert_threads' | '4' | Dedicated worker threads processing background asynchronous batch writes. |
Memory Management and 'max_memory_usage'
Configuring 'users.xml' Profiles
<profiles>
<default>
<max_memory_usage>32000000000</max_memory_usage>
<max_memory_usage_for_all_queries>128000000000</max_memory_usage_for_all_queries>
<load_balancing>in_order</load_balancing>
</default>
</profiles>- 'max_memory_usage': Restricts a single query to roughly 32 gigabytes of RAM before throwing an execution error instead of crashing the host.
- 'max_memory_usage_for_all_queries': Limits total cumulative memory consumption across all concurrent queries on the instance to 128 gigabytes, protecting underlying operating system stability.
Filesystem and Storage Optimization
Linux Mount and Sysctl Tuning
# Mount options in /etc/fstab for NVMe data partitions
UUID=your-uuid-here /var/lib/clickhouse ext4 noatime,nodiratime,errors=remount-ro,discard 0 0
# Tune kernel virtual memory and dirty page flushing for high write throughput
echo 'vm.swappiness=1' >> /etc/sysctl.d/99-clickhouse.conf
echo 'vm.dirty_background_ratio=5' >> /etc/sysctl.d/99-clickhouse.conf
echo 'vm.dirty_ratio=10' >> /etc/sysctl.d/99-clickhouse.conf
sysctl --systemMonitoring and Diagnostic Verification
SELECT
database,
table,
count() AS part_count,
sum(bytes_on_disk) / 1024 / 1024 / 1024 AS size_gb,
max(modification_time) AS last_modified
FROM system.parts
WHERE active
GROUP BY database, table
ORDER BY part_count DESC;