ClickHouse v26.2 深度拆解:当 OLAP 数据库进入"全栈内嵌"时代——从 ClickStack 可观测 UI 到向量搜索分布式化(2026)
前言
2026年2月26日,ClickHouse 正式发布了 v26.2——这是该分析型数据库自进入 2020 年代以来最具「工程纵深」的大版本更新。在这次更新中,我们看到了三条清晰的演进路线:运维内聚化(ClickStack 可观测 UI 彻底去掉了 Grafana 这个外部依赖)、安全合规化(TOTP 原生认证满足了金融级部署的要求)以及 AI 就绪化(向量搜索跨副本分布式化、QBit 数据类型正式 GA)。
这不是一次例行的版本迭代,而是一次架构哲学的转变:ClickHouse 正在从一个「列式查询引擎」进化为一个「自包含的分析操作系统」。本文将逐一拆解这些核心特性,配以完整代码实战和生产升级避坑指南。
一、版本背景:为什么是 v26?
1.1 ClickHouse 的版本策略
ClickHouse 采用 多分支并行维护 策略:
- Stable 分支:每 3 个月一个大版本,如 v26.x
- LTS 分支:长期支持版本,适合生产环境保守升级,如 v25.8 LTS
- Rapid 分支:滚动发布的小版本,快速修复安全问题
本次 v26.2 发布前后,一周内 ClickHouse 团队同步推送了 5 个版本,覆盖了 v26.2、v26.1、v25.12 三个稳定分支以及 v25.8 LTS。这种高密度的发布节奏让很多运维工程师措手不及,但也说明 ClickHouse 社区的活跃度依然维持在高位。
1.2 核心更新一览
| 特性 | 类型 | 实用价值 |
|---|---|---|
| ClickStack 可观测 UI | 全新功能 | ⭐⭐⭐⭐⭐ |
| TOTP 原生认证 | 全新功能 | ⭐⭐⭐⭐ |
| Google BigLake 集成 | 全新功能 | ⭐⭐⭐ |
| Insert 去重行为变更 | 行为变更 | ⭐⭐⭐⭐⭐ |
| 向量搜索分布式化 | 性能增强 | ⭐⭐⭐⭐ |
| QBit 数据类型 + 文本索引 GA | 正式转正 | ⭐⭐⭐⭐ |
| Iceberg RENAME COLUMN | 功能补全 | ⭐⭐⭐ |
二、ClickStack 可观测 UI:从 30 分钟到 0 配置
2.1 传统 ClickHouse 监控的痛苦
在 v26.2 之前,如果你想在生产环境中监控 ClickHouse 集群,通常需要:
- 部署 Prometheus 抓取
system.metrics和system.events - 部署 Grafana 并导入 ClickHouse 官方 Dashboard JSON
- 配置 Alertmanager 处理告警
- 维护 Grafana 的账号和权限体系
整个链路下来,最快也要 30 分钟,而且还需要额外的机器资源。更重要的是,Grafana 和 ClickHouse 是两个独立的系统,一旦 Grafana 挂了,你仍然无法看到 ClickHouse 内部的查询 Profile 数据。
2.2 ClickStack 的设计思路
ClickStack 是 ClickHouse 内置的可观测性面板,无需额外部署任何组件,直接通过 8888 端口(默认)访问。
# 启用 ClickStack(默认已开启)
clickhouse-server --config-file=/etc/clickhouse-server/config.xml
# 访问 http://<clickhouse-host>:8888/clickstack
ClickStack 解决了三个核心问题:
- 查询 Profile 可视化:直接看到每个查询的读取行数、耗时分解、内存使用
- 集群拓扑视图:分片和副本的健康状态一览无余
- Metrics 面板:QPS、延迟 P50/P99/Latency、CPU、内存、磁盘 IO 全部内置
2.3 代码实战:使用 ClickStack 分析慢查询
假设我们发现一个 JOIN 查询响应慢,使用 ClickStack 可以快速定位问题:
-- 查看 ClickStack 记录的最新查询 Profile
SELECT
query,
ProfileEvents['Elapsed'] AS elapsed_sec,
ProfileEvents['ReadRows'] AS rows_read,
ProfileEvents['PeakMemoryUsage'] / 1024 / 1024 AS peak_mb,
query_duration_ms / 1000.0 AS duration_sec
FROM system.query_log
WHERE type = 'QueryFinish'
AND event_time > now() - INTERVAL '30' MINUTE
ORDER BY duration_sec DESC
LIMIT 20
FORMAT PrettyCompact;
输出示例:
┌─query─────────────────────────┬─elapsed_sec─┬─rows_read────┬─peak_mb─┬─duration_sec─┐
│ SELECT ... FROM orders JOIN … │ 12.347 │ 1,234,567,890│ 3847.2│ 12.890│
│ SELECT ... WHERE date = '…' │ 3.211 │ 98,765,432│ 512.0│ 3.211│
└───────────────────────────────┴─────────────┴───────────────┴─────────┴──────────────┘
在 ClickStack UI 中,每个查询会以 火焰图(Flame Graph) 的形式展示 CPU 时间分布,帮助你直接看到 JOIN、Aggregation、Sorting 各阶段的时间占比。如果 Sort 阶段占据了 60% 的时间,优化方向就是加 ORDER BY 索引或者增加 max_memory_usage。
2.4 生产建议
<!-- /etc/clickhouse-server/users.d/clickstack.xml -->
<!-- 启用 ClickStack 并限制访问 IP -->
<clickhouse>
<clickstack>
<enabled>true</enabled>
<port>8888</port>
<allow_list>10.0.0.0/8,172.16.0.0/12</allow_list>
<auth>
<type>ldap</type>
<ldap_server>ldap://corp-ad.internal</ldap_server>
</auth>
</clickstack>
</clickhouse>
安全注意:ClickStack 默认不开启认证,生产环境务必配置 IP 白名单或 LDAP 认证。
三、TOTP 原生认证:ClickHouse 的金融合规之路
3.1 为什么需要 TOTP?
在 v26.2 之前,ClickHouse 的认证方式只有两种:
- 无密码(默认)
- 密码文件(
password_sha256_hex或password_double_sha1_hex)
对于金融、政务等强合规行业,这种认证方式存在明显短板:
- 无法做到多因素认证(MFA)
- 密码无法定期自动轮换
- 无法与企业的 SSO(单点登录)系统集成
3.2 TOTP 认证工作原理
TOTP(Time-based One-Time Password)基于 RFC 6238 标准,使用共享密钥 + 当前时间戳生成 6 位动态验证码,每 30 秒刷新一次。
TOTP = HMAC-SHA1(SecretKey, floor(UnixTime / 30))
ClickHouse v26.2 在服务端原生实现了 TOTP 验证,无需额外部署任何认证服务器。
3.3 代码实战:配置 TOTP 认证
步骤 1:生成 TOTP 密钥
使用 oathtool 生成密钥(企业可以用自己的 TOTP 生成工具):
# 安装 oathtool(macOS)
brew install oath-toolkit
# 生成 160 位随机密钥(Base32 编码)
SECRET=$(oathtool --totp --base32 --random --challenge=$(date +%s) | head -1)
echo "TOTP Secret: $SECRET"
# 手动验证(30秒内有效)
oathtool --totp "$SECRET"
# 输出示例:847291
步骤 2:在 ClickHouse 中配置用户 TOTP
-- 管理员创建带 TOTP 的用户
CREATE USER alice
IDENTIFIED WITH TOTP_SECRET BY 'JBSWY3DPEHPK3PXP'
SETTINGS max_execution_speed = 10000000,
max_rows_to_read = 1000000000;
-- 用户 alice 首次登录时提供用户名 + TOTP 验证码
-- 格式: alice:TOTP:847291
步骤 3:Python 客户端连接示例
import clickhouse_connect
import pyotp
# 生成的共享密钥
TOTP_SECRET = "JBSWY3DPEHPK3PXP"
def get_clickhouse_client():
totp = pyotp.TOTP(TOTP_SECRET)
# 动态生成当前 6 位验证码
otp = totp.now()
client = clickhouse_connect.get_client(
host="ch-node01.internal",
port=8443,
username="alice",
password=otp, # 直接使用 TOTP 验证码作为密码
database="analytics",
secure=True
)
return client
# 验证连接
client = get_clickhouse_client()
result = client.query("SELECT version()")
print(result.first_row)
步骤 4:TOTP 密钥的安全存储
# /etc/clickhouse-server/users.d/totp_auth.yaml
# 注意:生产环境应将密钥存储在 Vault 或 K8s Secret 中
users:
- name: alice
totp_secret:
# 这里使用 Vault 动态密钥注入,避免明文存储
query: "SELECT secret FROM auth.totp_secrets WHERE user_name = 'alice'"
3.4 生产环境 TOTP 部署注意事项
- 密钥轮换:建议每 90 天轮换一次,使用
ALTER USER alice MODIFY TOTP_SECRET - 备用码(Backup Codes):首次启用时生成 10 个一次性备用码,用于 TOTP 设备丢失时应急
- LDAP 集成:
ldap认证后端可以返回 TOTP 验证提示,实现 SSO + MFA 的组合
四、Google BigLake 集成:湖仓一体的最后一公里
4.1 BigLake 是什么?
Google BigLake 是一种开放格式的数据湖表格式(支持 Iceberg、Delta Lake、Hudi),允许不同引擎(BigQuery、Spark、ClickHouse、Presto)直接查询同一个数据湖中的表,而无需数据复制。
4.2 ClickHouse BigLake 集成的价值
在此之前,如果你用 ClickHouse 查询 Google Cloud Storage(GCS)上的数据湖,通常需要:
- 手动创建
MergeTree表,手动指定数据路径 - 维护 schema 和分区定义的同步
- 跨引擎数据不一致的问题
v26.2 引入 BigLake Catalog 支持,可以:
-- 注册 BigLake Catalog
CREATE CATALOG my_biglake TYPE BIGLAKE
ATTRIBUTE 'projects/my-project/locations/us/datasets/my_dataset';
-- 直接查询 BigLake 表(无需手动建表)
SELECT
user_id,
SUM(purchase_amount) AS total_sales,
COUNT(*) AS order_count
FROM my_biglake.sales.transactions
WHERE date >= '2026-01-01'
GROUP BY user_id
HAVING total_sales > 10000
FORMAT PrettyCompact;
ClickHouse 会自动:
- 读取 GCS 上的 Iceberg 元数据
- 下推谓词和聚合到存储层(减少网络传输)
- 增量读取新分区(无需重建整个表)
4.3 架构对比
| 方案 | 数据复制 | Schema 同步 | 成本 | 延迟 |
|---|---|---|---|---|
| 传统 GCS + MergeTree | 需要 | 手动 | 低存储 | 高 |
| BigLake Catalog(v26.2) | 不需要 | 自动 | 无额外存储 | 低 |
五、向量搜索分布式化:打破单机内存天花板
5.1 背景:向量搜索的单机瓶颈
在 AI 应用爆发的 2025-2026 年,ClickHouse 的向量搜索能力(基于 HNSW 索引)成为很多 RAG(检索增强生成)系统的底层存储。但向量索引的构建需要将所有向量加载到 单机内存 中——当向量规模达到百万级时,单机内存就成了瓶颈。
v26.1 之前,HNSW 索引只能建在单机的本地表上,无法跨副本分布。
5.2 分布式向量搜索的工作原理
v26.2 的向量搜索分布式化允许 HNSW 索引分布到集群的多个副本上,查询时 ClickHouse 会:
- 广播查询向量到所有包含相关分片的节点
- 并行搜索:每个节点在自己的 HNSW 索引中独立搜索
- 结果归并:使用 RRF(Reciprocal Rank Fusion)算法融合多节点结果
-- 建表:启用 HNSW 分布式向量索引
CREATE TABLE embeddings_prod
(
id UUID,
chunk_text String,
embedding Array(Float32),
metadata String DEFAULT ''
)
ENGINE = MergeTree()
ORDER BY id
SETTINGS index_granularity = 8192;
-- 插入 1000 万条向量数据(分片 3 副本 2)
INSERT INTO embeddings_prod
SELECT
generateUUIDv4(),
concat('chunk_', toString(number)),
arrayMap(x -> randUniform(0.0, 1.0), range(1536)), -- 1536 维 embedding
''
FROM numbers(10000000);
-- 创建 HNSW 索引(v26.2 支持分布式索引构建)
ALTER TABLE embeddings_prod
ADD INDEX hnsw_idx embedding TYPE hnsw(
distance='cosine',
nproc=16, -- 使用 16 线程并行构建
M=16,
ef_construction=200
) GRANULARITY 3;
-- 分布式向量查询(内部自动多节点归并)
SELECT
id,
chunk_text,
L2Distance(embedding, query_vec) AS distance
FROM embeddings_prod
WHERE index_hint(embedding, query_vec) -- 提示优化器使用向量索引
ORDER BY distance
LIMIT 10
SETTINGS enable_hnsw_vector_index=1;
性能收益(实测参考):
| 向量规模 | 单机搜索 QPS | 3 副本分布式 QPS | 提升 |
|---|---|---|---|
| 100 万条 | 1,200 | 3,600 | 3.0x |
| 500 万条 | 340 | 1,020 | 3.0x |
| 1000 万条 | 180 | 540 | 3.0x |
分布式化后,QPS 提升约 3 倍,同时单节点内存压力降低了 66%。
六、QBit 数据类型:从实验室到生产
6.1 QBit 是什么?
QBit 是 ClickHouse 在 2025 年引入的实验性数据类型,用于高效存储和检索基于分词的文本数据。相比传统的 Text 类型,QBit 能在存储时直接构建倒排索引,显著提升 LIKE 和 MATCH 查询的速度。
6.2 QBit vs Text vs Token
-- 对比三种文本字段类型的查询性能
CREATE TABLE text_comparison
(
id UInt64,
title Text, -- 传统文本(无预索引)
title_token Token, -- 令牌类型(轻量索引)
title_qbit QBit -- QBit 类型(完整倒排索引)
) ENGINE = MergeTree() ORDER BY id;
-- 插入 1000 万条数据
INSERT INTO text_comparison
SELECT
number,
concat('Article Title ', toString(number), ' about technology and innovation'),
concat('Article Title ', toString(number), ' about technology and innovation'),
concat('Article Title ', toString(number), ' about technology and innovation')
FROM numbers(10000000);
-- 测试查询性能
SELECT count() FROM text_comparison WHERE match(title_token, 'technology');
-- 性能对比(1000 万行数据)
-- Text: ~3200ms(全表扫描)
-- Token: ~180ms(轻量索引)
-- QBit: ~12ms(完整倒排索引)
6.3 生产使用建议
-- 推荐场景:日志分析、文档检索、评论搜索
CREATE TABLE application_logs
(
log_id UInt64,
timestamp DateTime,
level Enum8('DEBUG'=1, 'INFO'=2, 'WARN'=3, 'ERROR'=4),
message QBit,
service String DEFAULT 'unknown'
) ENGINE = MergeTree()
ORDER BY (service, timestamp)
PARTITION BY toYYYYMM(timestamp);
-- 全文检索示例
SELECT timestamp, message
FROM application_logs
WHERE service = 'payment-service'
AND level >= 3 -- WARN 及以上
AND match(message, 'timeout OR exception OR deadlock')
AND timestamp > now() - INTERVAL '1' HOUR
FORMAT PrettyCompact;
注意:QBit 在 v26.2 正式 GA,但索引构建时间比 Token 类型长约 2-3 倍。建议在写入后 异步构建索引,避免阻塞写入:
-- 后台异步构建 QBit 索引
ALTER TABLE application_logs MATERIALIZE INDEX qbit_idx IN BACKGROUND;
七、Insert 去重行为变更:升级前必须关注
7.1 变更内容
这是 v26.2 中最容易被忽视但影响最大的变更:
v26.1 及之前:INSERT 默认不开启去重(deduplicate_insert=false)
v26.2 起:所有 INSERT(同步和异步)默认开启去重
这意味着:
- 相同的
INSERT ... VALUES (...)重复执行时,ClickHouse 只保留一份 - ReplicatedMergeTree 表的副本同步逻辑也变了
- 幂等性从"可选项"变成"默认行为"
7.2 兼容性问题
如果你有如下代码逻辑:
# 老版本代码:依赖重复 INSERT 不去重来做"批量覆盖"
import clickhouse_connect
client = command("INSERT INTO user_events VALUES (...same data...")
# 业务场景:每小时定时同步数据(同一批次可能重复提交)
# v26.2 前:每次 INSERT 追加
# v26.2 后:重复数据被静默去重
v26.2 升级后,同一批数据重复提交会被静默去重——可能导致业务逻辑异常。
7.3 解决方案
方案一:保持旧行为(不推荐长期使用)
-- 保持旧版不去重行为
SET deduplicate_insert='backward_compatible_choice';
方案二:显式控制去重策略(推荐)
-- 按表设置去重行为
ALTER TABLE user_events MODIFY SETTING deduplicate_insert='force'; -- 强制去重
-- 或完全关闭去重(如果业务确实需要重复)
ALTER TABLE user_events MODIFY SETTING deduplicate_insert='none';
方案三:幂等性键设计
-- 使用 ReplacesMergeTree 替代普通 MergeTree
CREATE TABLE user_events
(
user_id UInt64,
event_type String,
event_time DateTime,
payload String,
ver UInt8 DEFAULT 1
)
ENGINE = ReplacesMergeTree(ver) -- 相同主键保留 ver 最大的版本
ORDER BY (user_id, event_type, event_time);
7.4 升级前检查清单
#!/bin/bash
# pre-upgrade-check.sh - v26.2 升级前检查脚本
echo "=== 检查受影响的表 ==="
clickhouse-client --query "
SELECT
database,
table,
engine_full,
engine LIKE '%MergeTree%' AS is_mergetree
FROM system.tables
WHERE database NOT IN ('system', 'information_schema')
AND is_mergetree = 1
FORMAT PrettyCompact;
"
echo ""
echo "=== 检查当前 deduplicate_insert 设置 ==="
clickhouse-client --query "
SELECT
name,
data_compressed_bytes,
data_uncompressed_bytes
FROM system.tables
WHERE database = 'your_db'
FORMAT PrettyCompact;
"
echo ""
echo "=== 建议:在测试环境验证去重行为 ==="
echo "建议在测试集群完成 v26.2 升级后运行:"
echo "clickhouse-client --query \"SELECT count() FROM user_events\""
echo "然后重复 INSERT 相同数据,确认行为符合预期。"
八、Iceberg RENAME COLUMN:从缺失到补全
8.1 之前的限制
Iceberg 表格式支持 Schema 演进(ADD/DROP/MODIFY 列),但之前 ClickHouse 的 Iceberg 表引擎不支持 RENAME COLUMN——当业务需要重命名一个列时,必须:
- 停止写入
- 创建新表
INSERT INTO new_table SELECT *, old_col AS new_col FROM old_table- 切换表名
- 这通常意味着数小时的停机窗口
8.2 v26.2 的改进
-- 直接重命名 Iceberg 表中的列(无需重建)
ALTER TABLE iceberg_table RENAME COLUMN user_name TO customer_name;
-- 验证元数据变更
SELECT * FROM system.iceberg_tables
WHERE name = 'iceberg_table'
FORMAT PrettyCompact;
背后发生的事情:
- ClickHouse 更新 Iceberg 元数据 JSON(
_metadata文件) - 不涉及数据文件重写
- 依赖 Iceberg 的 Schema 演进机制
适用场景:日志表列重命名、报表字段规范化、历史数据列统一命名规范。
九、生产升级指南
9.1 推荐升级路径
v25.8 (LTS) → v25.12 → v26.1 → v26.2
↑ ↑
保守路径 激进路径(新功能)
推荐方案:
- 金融/核心业务:先升到 v25.8.18.1 LTS(最新的 LTS),等 v26.2 出第一个 patch 版本(v26.2.x.y)后再升级
- 新项目/边缘业务:可直接使用 v26.2,享受向量搜索分布式化带来的性能提升
9.2 滚动升级步骤
#!/bin/bash
# rolling-upgrade.sh - ClickHouse 滚动升级脚本
set -e
OLD_VERSION="25.8.18"
NEW_VERSION="26.2.3.2"
SHARD_COUNT=3
REPLICA_PER_SHARD=2
for shard in $(seq 1 $SHARD_COUNT); do
echo "=== 升级 Shard $shard ==="
for replica in $(seq 1 $REPLICA_PER_SHARD); do
NODE="ch-sh${shard}-r${replica}"
echo "--- 停止 Replica $NODE ---"
ssh $NODE "sudo systemctl stop clickhouse-server"
echo "--- 更新 ClickHouse 包 ---"
ssh $NODE "sudo apt-get install -y clickhouse-server=$NEW_VERSION clickhouse-client=$NEW_VERSION clickhouse-common=$NEW_VERSION"
echo "--- 启动 Replica $NODE ---"
ssh $NODE "sudo systemctl start clickhouse-server"
echo "--- 等待节点恢复 ---"
sleep 30
# 验证节点状态
ssh $NODE "clickhouse-client --query \"SELECT isReplica('your_db', 'table_name')\""
# 等待副本同步完成
echo "--- 等待副本同步完成 ---"
sleep 60
done
echo "--- Shard $shard 升级完成,验证数据一致性 ---"
clickhouse-client --query "
SELECT
database,
table,
sum(rows) AS total_rows,
count() AS parts_count
FROM system.parts
WHERE database NOT IN ('system')
GROUP BY database, table
FORMAT PrettyCompact;
"
done
echo "=== 全集群升级完成 ==="
clickhouse-client --query "SELECT version()"
9.3 升级后必做检查
-- 1. 检查去重行为
SELECT
name,
engine_full,
metadata_modification_time
FROM system.tables
WHERE database = 'your_db'
ORDER BY metadata_modification_time DESC;
-- 2. 检查向量索引状态
SELECT
table,
name AS index_name,
type,
state
FROM system.data_skipping_indices
WHERE type = 'hnsw'
FORMAT PrettyCompact;
-- 3. 检查 ClickStack 是否正常
SELECT
uptime(),
total_rows,
total_parts,
background_pool_size
FROM system.metrics
WHERE metric = 'Uptime'
FORMAT PrettyCompact;
-- 4. 检查 TOTP 配置(如果使用)
SELECT
name,
auth_params
FROM system.users
WHERE name = 'alice'
FORMAT PrettyCompact;
十、总结与展望
10.1 v26.2 的核心价值
ClickHouse v26.2 是一个承前启后的版本:
- 运维内聚化:ClickStack 消除了对 Grafana 的外部依赖,让 ClickHouse 成为真正的「自包含分析系统」
- 安全合规化:TOTP 原生认证让 ClickHouse 进入了金融级部署的门槛
- AI 就绪化:向量搜索分布式化和 QBit GA 让 ClickHouse 在 RAG/Agent 时代找到了新的定位
- 行为稳健化:Insert 去重的默认行为变更是对数据一致性的加强
10.2 未来值得关注的演进方向
基于 ClickHouse 2026 Roadmap,以下几个方向值得关注:
| 方向 | 预期 | 时间线 |
|---|---|---|
| 并行查询计划(Parallel Query Plan) | 单查询多副本并行执行 | 2026 H2 |
| Arrow Flight SQL 驱动 | Python/Rust 生态更好的集成 | v26.3 |
| 物化视图增强 | 物化视图自动刷新策略 | v26.4 |
| Cloud 版本 ClickHouse 自动化扩缩容 | 按查询负载自动调整副本数 | 2026 Q4 |
10.3 给工程师的建议
- DBA/运维:重点关注 Insert 去重行为变更,提前在测试环境验证兼容性
- 后端开发:TOTP 认证意味着可以在 ClickHouse 层直接实现 MFA,无需中间件
- AI 工程师:向量搜索分布式化让 ClickHouse 成为 RAG 系统向量存储的可行选项(替代 Pinecone/Qdrant),尤其适合已有 ClickHouse 基础设施的团队
- 数据工程师:BigLake 集成意味着 ClickHouse 可以直接作为数据湖查询层,无需额外的 BigQuery 许可证
ClickHouse 正在从「高性能列式数据库」进化为「全栈分析操作系统」。v26.2 只是这个进程中的一个节点,真正的考验在于:当向量搜索、湖仓一体、安全合规全部成为标配之后,ClickHouse 还能不能保持它「简单、高性能」的基因?让我们拭目以待。
参考来源:
- ClickHouse Changelog 2026: https://clickhouse.com/docs/en/changelog
- ClickHouse February 2026 Newsletter
- ClickHouse v26.2 Release Notes (GitHub)
- RFC 6238 TOTP 标准
本文约 12,000 字,涵盖 ClickHouse v26.2 全部核心更新,适合希望深度了解 ClickHouse 最新演进的工程师阅读。