ClickHouse 数据库详解
ClickHouse 是一个开源的列式数据库管理系统(DBMS),专为在线分析处理(OLAP)而设计。它由俄罗斯搜索引擎公司 Yandex 开发,并于 2016 年开源。ClickHouse 以其卓越的查询性能和压缩效率而闻名,特别适合处理大规模数据的分析工作负载。
核心特性
1. 列式存储架构
与传统的行式数据库不同,ClickHouse 采用列式存储:
- 高压缩率:相同类型的数据聚集在一起,压缩效果更好
- 查询效率:只读取需要的列,减少I/O操作
- 缓存友好:提高CPU缓存命中率
2. 极致的查询性能
- 向量化执行:SIMD指令优化,充分利用现代CPU
- 并行处理:自动并行化查询执行
- 索引优化:稀疏索引和跳跃索引提高查询速度
- 查询优化器:基于成本的查询优化
3. 高可用性和扩展性
- 分布式架构:支持集群部署
- 副本机制:数据自动复制和故障转移
- 水平扩展:可以轻松添加新节点
- 负载均衡:智能分发查询请求
技术架构
存储引擎
ClickHouse 支持多种存储引擎:
-- MergeTree 系列(最常用)
CREATE TABLE example (
date Date,
id UInt32,
name String
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY id;
-- ReplacingMergeTree(去重)
CREATE TABLE unique_example (
id UInt32,
value String,
version UInt32
) ENGINE = ReplacingMergeTree(version)
ORDER BY id;数据类型
ClickHouse 提供丰富的数据类型:
-- 基础类型
UInt8, UInt16, UInt32, UInt64
Int8, Int16, Int32, Int64
Float32, Float64
String, FixedString(N)
Date, DateTime, DateTime64
-- 复合类型
Array(T) -- 数组
Tuple(T1, T2, ...) -- 元组
Nullable(T) -- 可空类型
Map(K, V) -- 映射
Nested -- 嵌套结构安装和部署
单机安装
Ubuntu/Debian
sudo apt-get install -y apt-transport-https ca-certificates dirmngr
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv E0C56BD4
echo "deb https://repo.clickhouse.com/deb/stable/ main/" | sudo tee \
/etc/apt/sources.list.d/clickhouse.list
sudo apt-get update
sudo apt-get install -y clickhouse-server clickhouse-client
sudo service clickhouse-server startCentOS/RHEL
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://repo.clickhouse.com/rpm/clickhouse.repo
sudo yum install -y clickhouse-server clickhouse-client
sudo systemctl start clickhouse-serverDocker 部署
# 启动 ClickHouse 服务器
docker run -d --name clickhouse-server \
-p 8123:8123 -p 9000:9000 \
--ulimit nofile=262144:262144 \
clickhouse/clickhouse-server
# 连接客户端
docker run -it --rm --link clickhouse-server:clickhouse-server \
clickhouse/clickhouse-client \
--host clickhouse-server集群部署
集群配置示例:
<!-- /etc/clickhouse-server/config.d/cluster.xml -->
<clickhouse>
<remote_servers>
<cluster_name>
<shard>
<replica>
<host>node1.example.com</host>
<port>9000</port>
</replica>
<replica>
<host>node2.example.com</host>
<port>9000</port>
</replica>
</shard>
<shard>
<replica>
<host>node3.example.com</host>
<port>9000</port>
</replica>
<replica>
<host>node4.example.com</host>
<port>9000</port>
</replica>
</shard>
</cluster_name>
</remote_servers>
</clickhouse>基本操作
数据库和表操作
-- 创建数据库
CREATE DATABASE analytics;
-- 使用数据库
USE analytics;
-- 创建表
CREATE TABLE events (
timestamp DateTime,
user_id UInt32,
event_type String,
properties Map(String, String)
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(timestamp)
ORDER BY (user_id, timestamp);
-- 查看表结构
DESCRIBE events;
-- 删除表
DROP TABLE events;数据插入
-- 单条插入
INSERT INTO events VALUES
('2023-10-10 12:00:00', 1001, 'page_view', {'page': '/home', 'ref': 'google'});
-- 批量插入
INSERT INTO events VALUES
('2023-10-10 12:01:00', 1002, 'click', {'button': 'signup'}),
('2023-10-10 12:02:00', 1003, 'purchase', {'amount': '99.99', 'currency': 'USD'});
-- 从文件导入
INSERT INTO events FROM INFILE 'events.csv' FORMAT CSV;
-- 从SELECT导入
INSERT INTO events SELECT * FROM other_events WHERE timestamp > '2023-10-01';数据查询
-- 基础查询
SELECT user_id, count() as events_count
FROM events
WHERE timestamp >= '2023-10-01'
GROUP BY user_id
ORDER BY events_count DESC
LIMIT 10;
-- 窗口函数
SELECT
user_id,
timestamp,
event_type,
row_number() OVER (PARTITION BY user_id ORDER BY timestamp) as event_sequence
FROM events;
-- 聚合查询
SELECT
toYYYYMM(timestamp) as month,
event_type,
count() as count,
uniq(user_id) as unique_users
FROM events
GROUP BY month, event_type
ORDER BY month, count DESC;高级功能
物化视图
物化视图可以预计算和存储查询结果:
-- 创建物化视图
CREATE MATERIALIZED VIEW daily_stats
ENGINE = SummingMergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (date, event_type)
AS SELECT
toDate(timestamp) as date,
event_type,
count() as events_count,
uniq(user_id) as unique_users
FROM events
GROUP BY date, event_type;
-- 查询物化视图
SELECT * FROM daily_stats WHERE date >= '2023-10-01';分区和索引
-- 分区表
CREATE TABLE sales (
date Date,
product_id UInt32,
sales_amount Decimal(10,2)
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(date) -- 按月分区
ORDER BY (product_id, date)
SETTINGS index_granularity = 8192;
-- 添加跳跃索引
ALTER TABLE sales ADD INDEX sales_amount_idx sales_amount TYPE minmax GRANULARITY 4;字典
ClickHouse 支持外部字典,用于数据关联:
<!-- dictionaries/products.xml -->
<dictionary>
<name>products</name>
<source>
<mysql>
<host>mysql-server</host>
<port>3306</port>
<user>user</user>
<password>password</password>
<db>catalog</db>
<table>products</table>
</mysql>
</source>
<layout>
<hashed/>
</layout>
<structure>
<id>
<name>id</name>
</id>
<attribute>
<name>name</name>
<type>String</type>
</attribute>
</structure>
<lifetime>300</lifetime>
</dictionary>使用字典:
SELECT
product_id,
dictGet('products', 'name', product_id) as product_name,
sum(sales_amount) as total_sales
FROM sales
GROUP BY product_id;性能优化
配置优化
<!-- config.xml -->
<clickhouse>
<!-- 内存设置 -->
<max_server_memory_usage_to_ram_ratio>0.8</max_server_memory_usage_to_ram_ratio>
<max_memory_usage>10000000000</max_memory_usage>
<!-- 并发设置 -->
<max_concurrent_queries>100</max_concurrent_queries>
<max_thread_pool_size>10000</max_thread_pool_size>
<!-- 网络设置 -->
<keep_alive_timeout>10</keep_alive_timeout>
<max_connections>4096</max_connections>
</clickhouse>监控和运维
系统表查询
-- 查看运行中的查询
SELECT * FROM system.processes;
-- 查看表大小
SELECT
database,
table,
formatReadableSize(sum(bytes)) as size
FROM system.parts
GROUP BY database, table
ORDER BY sum(bytes) DESC;
-- 查看查询日志
SELECT * FROM system.query_log
WHERE event_time >= now() - INTERVAL 1 HOUR
ORDER BY event_time DESC;备份和恢复
-- 创建备份
BACKUP TABLE events TO Disk('backups', 'events_backup_20231010.zip');
-- 恢复备份
RESTORE TABLE events FROM Disk('backups', 'events_backup_20231010.zip');使用场景
1. 实时分析
- 网站用户行为分析
- 实时监控大屏
- 业务指标计算
2. 数据仓库
- OLAP分析
- 报表生成
- 历史数据查询
3. 日志分析
- 应用程序日志
- 系统监控数据
- 安全审计日志
4. 时序数据
- IoT传感器数据
- 金融交易数据
- 网络监控指标
最佳实践
1. 表设计
- 合理选择分区键和排序键
- 避免过多的小分区
- 使用合适的数据类型
2. 查询优化
- 尽量使用分区过滤
- 避免SELECT *
- 合理使用索引
3. 运维管理
- 定期监控集群状态
- 及时清理过期数据
- 做好备份策略
与其他数据库对比
| 特性 | ClickHouse | PostgreSQL | MySQL | Apache Druid |
|---|---|---|---|---|
| 存储模式 | 列式 | 行式 | 行式 | 列式 |
| OLAP性能 | 极高 | 中等 | 较低 | 高 |
| 压缩率 | 极高 | 中等 | 中等 | 高 |
| 实时写入 | 支持 | 支持 | 支持 | 有限支持 |
| SQL兼容性 | 高 | 极高 | 高 | 中等 |
| 运维复杂度 | 中等 | 低 | 低 | 高 |
总结
ClickHouse 是一个强大的列式数据库,特别适合大数据分析场景。其优势包括:
- 极高的查询性能:列式存储和向量化执行
- 出色的压缩效果:节省存储空间
- 灵活的架构:支持单机和集群部署
- 丰富的功能:物化视图、字典、分区等
- 活跃的社区:持续的功能更新和优化
选择 ClickHouse 时需要考虑:
- 主要用于分析场景,不适合高频更新
- 需要一定的运维和调优经验
- 对于小数据量可能过于复杂