ClickHouse 列式数据库
一句话概述:ClickHouse 是俄罗斯Yandex开源的列式数据库,专为实时分析设计,能在秒级完成数十亿行数据的聚合查询。
核心知识点表
| 概念 | 白话解释 |
|---|
| 列式存储 | 数据按列存而不是按行存,统计分析时只读需要的列,极快 |
| MergeTree | ClickHouse核心表引擎,数据按排序键存储并定期合并 |
| 分区(Partition) | 把数据按时间等维度分成多个"抽屉",查询时只打开需要的 |
| 主键(Order By) | 排序键,决定数据在磁盘上的排列顺序,影响查询性能 |
| Materialized View | 物化视图,数据写入时自动计算聚合结果,查询秒出 |
| TTL | 数据自动过期删除,比如"30天前的详细数据自动删" |
| 副本(Replica) | 数据多副本存储,防丢失 |
| 分片(Shard) | 数据分布在多台机器上,处理海量数据 |
版本信息(2026年5月)
- 最新版本:ClickHouse 26.3.10.60
- 2025年共277个新功能、319项性能优化
- 亮点:向量搜索GA、轻量UPDATE、SharedCatalog
安装配置
方式一:快速安装(推荐学习用)
# 一键安装脚本(Linux/macOS)
curl https://clickhouse.com/ | sh # 下载可执行文件
# 启动服务器
./clickhouse server # 前台运行
# 另开终端,连接客户端
./clickhouse client # 进入SQL交互界面
方式二:APT安装(Ubuntu/Debian)
# 添加ClickHouse官方仓库
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | \
sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] \
https://packages.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 systemctl start clickhouse-server # 启动服务
sudo systemctl enable clickhouse-server # 开机自启
# 连接
clickhouse-client # 命令行客户端
# 默认端口:HTTP 8123,Native 9000
方式三:Docker
# 拉取镜像并启动
docker run -d \
--name clickhouse \
-p 8123:8123 \
-p 9000:9000 \
-v clickhouse_data:/var/lib/clickhouse \
clickhouse/clickhouse-server:latest
# 连接
docker exec -it clickhouse clickhouse-client
基本使用
创建数据库和表
-- 创建数据库
CREATE DATABASE IF NOT EXISTS analytics; -- 创建analytics数据库
USE analytics; -- 切换到该数据库
-- 创建表(MergeTree引擎)
CREATE TABLE events (
event_id UUID DEFAULT generateUUIDv4(), -- 事件ID,自动生成UUID
user_id UInt64, -- 用户ID(无符号64位整数)
event_type LowCardinality(String), -- 事件类型(低基数优化)
event_time DateTime DEFAULT now(), -- 事件时间,默认当前时间
properties String, -- JSON属性
amount Decimal(10, 2), -- 金额
country LowCardinality(String) -- 国家
)
ENGINE = MergeTree() -- 使用MergeTree引擎
PARTITION BY toYYYYMM(event_time) -- 按年月分区(202601, 202602...)
ORDER BY (user_id, event_time) -- 按用户ID和时间排序(重要!影响查询性能)
TTL event_time + INTERVAL 1 YEAR -- 1年后自动删除
SETTINGS index_granularity = 8192; -- 索引粒度
插入数据
-- 单条插入
INSERT INTO events (user_id, event_type, amount, country) VALUES
(1001, 'purchase', 99.99, 'CN'),
(1002, 'login', 0, 'US'),
(1001, 'purchase', 49.50, 'CN');
-- 从CSV文件导入
INSERT INTO events FORMAT CSVWithNames
-- 然后在命令行:
-- cat data.csv | clickhouse-client --query="INSERT INTO events FORMAT CSVWithNames"
-- 从其他表插入
INSERT INTO events_archive
SELECT * FROM events
WHERE event_time < now() - INTERVAL 30 DAY;
查询数据
-- 基本查询
SELECT * FROM events LIMIT 10; -- 查看前10行
-- 聚合查询(ClickHouse的强项)
SELECT
country,
event_type,
count() AS cnt, -- 事件数
sum(amount) AS total_amount, -- 总金额
avg(amount) AS avg_amount, -- 平均金额
uniq(user_id) AS unique_users -- 去重用户数(近似)
FROM events
WHERE event_time >= '2026-01-01' -- 分区剪枝,只读2026年的数据
GROUP BY country, event_type
ORDER BY total_amount DESC
LIMIT 20;
-- 时间序列分析
SELECT
toStartOfHour(event_time) AS hour, -- 按小时截断
count() AS events_per_hour
FROM events
WHERE event_time >= now() - INTERVAL 24 HOUR -- 最近24小时
GROUP BY hour
ORDER BY hour;
高级用法
物化视图(实时聚合)
-- 创建存放聚合结果的表
CREATE TABLE daily_stats (
date Date, -- 日期
event_type String, -- 事件类型
total_events UInt64, -- 总事件数
total_amount Decimal(18, 2), -- 总金额
unique_users UInt64 -- 独立用户数
)
ENGINE = SummingMergeTree() -- 自动合并同主键的行
ORDER BY (date, event_type);
-- 创建物化视图(数据写入events时自动聚合到daily_stats)
CREATE MATERIALIZED VIEW daily_stats_mv
TO daily_stats -- 结果写入哪个表
AS SELECT
toDate(event_time) AS date,
event_type,
count() AS total_events,
sum(amount) AS total_amount,
uniq(user_id) AS unique_users
FROM events
GROUP BY date, event_type;
-- 以后查聚合数据直接查daily_stats,秒出结果
SELECT * FROM daily_stats WHERE date = today();
JSON数据处理
-- ClickHouse可以直接操作JSON字段
SELECT
user_id,
JSONExtractString(properties, 'browser') AS browser, -- 提取浏览器
JSONExtractInt(properties, 'page_views') AS views -- 提取页面浏览数
FROM events
WHERE JSONHas(properties, 'browser'); -- 只查有browser字段的
表函数查询外部数据
-- 直接查询远程MySQL
SELECT * FROM mysql(
'host:3306', 'database', 'table', 'user', 'password'
);
-- 直接查询PostgreSQL
SELECT * FROM postgresql(
'host:5432', 'database', 'table', 'user', 'password'
);
-- 查询S3上的文件
SELECT * FROM s3(
'https://bucket.s3.amazonaws.com/data.parquet',
'AKID', 'SECRET', 'Parquet'
);
-- 查询URL
SELECT * FROM url('https://api.example.com/data.json', JSONEachRow);
性能优化
-- 查看查询执行计划
EXPLAIN SELECT count() FROM events WHERE user_id = 1001;
-- 查看索引使用情况
EXPLAIN indexes = 1
SELECT * FROM events WHERE user_id = 1001;
-- 添加跳数索引(二级索引)
ALTER TABLE events
ADD INDEX idx_country (country) TYPE set(100) GRANULARITY 4;
-- set(100):记录每个颗粒中country的不同值集合
-- 查询 WHERE country = 'CN' 时可以跳过不含'CN'的颗粒
常见报错与解决
| 报错信息 | 原因 | 解决方案 |
|---|
DB::Exception: Memory limit exceeded | 查询内存超限 | SET max_memory_usage = 10000000000增大限制 |
Too many parts | 写入太频繁,小文件太多 | 批量写入,不要一条条INSERT |
Table is in readonly mode | 磁盘空间不足 | 清理磁盘空间 |
Connection refused | 服务没启动 | sudo systemctl start clickhouse-server |
Authentication failed | 用户名密码错误 | 检查/etc/clickhouse-server/users.xml |
Code: 62. Syntax error | SQL语法有误 | ClickHouse SQL有些地方和标准SQL不同 |
速查表
-- ===== 数据库操作 =====
SHOW DATABASES; -- 列出数据库
CREATE DATABASE db_name; -- 创建数据库
USE db_name; -- 切换数据库
SHOW TABLES; -- 列出表
DESCRIBE table_name; -- 查看表结构
-- ===== 数据操作 =====
INSERT INTO t VALUES (...); -- 插入
SELECT ... FROM t; -- 查询
ALTER TABLE t DELETE WHERE ...; -- 删除(异步)
ALTER TABLE t UPDATE col=val WHERE ...; -- 更新(异步)
TRUNCATE TABLE t; -- 清空表
DROP TABLE t; -- 删除表
-- ===== 常用函数 =====
count(), sum(), avg(), min(), max() -- 聚合
uniq(col) -- 近似去重计数
uniqExact(col) -- 精确去重
quantile(0.95)(col) -- 95分位数
topK(10)(col) -- Top 10
arrayJoin(arr) -- 数组展开
-- ===== 时间函数 =====
now() -- 当前时间
today() -- 今天日期
toDate(dt), toDateTime(s) -- 类型转换
toStartOfHour/Day/Week/Month() -- 时间截断
dateDiff('day', d1, d2) -- 日期差
-- ===== 系统表 =====
SELECT * FROM system.parts; -- 数据分片信息
SELECT * FROM system.query_log; -- 查询日志
SELECT * FROM system.metrics; -- 系统指标
同类工具对比
| 特性 | ClickHouse | DuckDB | PostgreSQL | Elasticsearch |
|---|
| 类型 | 分布式OLAP | 嵌入式OLAP | 通用RDBMS | 搜索引擎 |
| 数据规模 | PB级 | GB-TB级 | TB级 | TB级 |
| 查询延迟 | 毫秒-秒级 | 毫秒级 | 毫秒-秒级 | 毫秒级 |
| 并发写入 | 高 | 单写 | 高 | 高 |
| 部署 | 服务器/集群 | 无需部署 | 服务器 | 集群 |
| 适合场景 | 实时大规模分析 | 本地分析 | 通用业务 | 日志搜索 |
面试建议:ClickHouse面试重点理解列式存储原理(为什么分析查询快?因为只读需要的列,压缩率高),MergeTree引擎工作原理(数据分part,后台合并),以及物化视图如何实现实时聚合。