跳转至

ClickHouse 列式数据库

一句话概述:ClickHouse 是俄罗斯Yandex开源的列式数据库,专为实时分析设计,能在秒级完成数十亿行数据的聚合查询。

核心知识点表

概念白话解释
列式存储数据按列存而不是按行存,统计分析时只读需要的列,极快
MergeTreeClickHouse核心表引擎,数据按排序键存储并定期合并
分区(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 errorSQL语法有误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;  -- 系统指标

同类工具对比

特性ClickHouseDuckDBPostgreSQLElasticsearch
类型分布式OLAP嵌入式OLAP通用RDBMS搜索引擎
数据规模PB级GB-TB级TB级TB级
查询延迟毫秒-秒级毫秒级毫秒-秒级毫秒级
并发写入单写
部署服务器/集群无需部署服务器集群
适合场景实时大规模分析本地分析通用业务日志搜索

面试建议:ClickHouse面试重点理解列式存储原理(为什么分析查询快?因为只读需要的列,压缩率高),MergeTree引擎工作原理(数据分part,后台合并),以及物化视图如何实现实时聚合。