第 3 章 · 数据类型详解

三个交互演示:① LowCardinality 字典编码 · ② Nullable 双列布局 · ③ Array / Map / Nested 列存物理布局

看 LowCardinality(String) 怎么把字符串列「字典化」

输入一组重复字符串值(每行一个),点「▶ 编码」看:原列 → 字典 → codes 三段布局,以及节省的字节数。

📦 原始 String 列(每值都完整存)
📚 字典 dictionary(去重后排序)
🔢 codes 列(每值变成下标整数)
原始 String 占用
LowCardinality 占用(字典 + codes)
压缩比
codes 字宽
结论: 低基数列收益巨大(10 个值 / 1000 行 → 缩小 5~10 倍);高基数列反而变大(900 全唯一 → 字典 + codes 一起比原值还大)。生产经验:基数 < 10000 强烈建议套 LowCardinality。

看 Nullable(Int32) 比 Int32 多了什么

滑动控制 NULL 比例,看 Nullable 列是怎么由「原值列 + null mask 列」两列拼起来的,以及多花多少存储:

Int32 列布局(单列)
v.bin(数据列)
Nullable(Int32) 列布局(双列)
v.bin(数据列)
v.null.bin(null 掩码)
Int32 占用
Nullable(Int32) 占用
额外开销
关键: Nullable 不只是「逻辑标志」 —— 它在物理上多出一列 .null.bin,每行 1 字节。原列越窄、NULL 比例越高,相对开销越显著(UInt8 列直接翻倍)。生产建议:能用 -1 / '' 替代就别上 Nullable

JSON 输入 → ClickHouse 列存物理布局

选一种复合类型,看同一份 JSON 数据在磁盘上拆成几个文件、怎么布局:

📥 输入 JSON(INSERT FORMAT JSONEachRow)

      
💾 磁盘上的列文件

📊 复合类型选型速查

类型底层布局典型用途注意
Array(T)size 列 + data 扁平数组标签 / 分数 / 元素列表大量高阶函数支持
Tuple(T1,T2,...)每个字段独立列存(lng,lat)、复合键、临时打包本质是「多列封装」
Map(K,V)等价 Tuple(Array(K), Array(V))少量稀疏 KV取 key 是 O(N),不要乱用
Nested(...)多列并行数组订单 items、子表场景各字段长度必须相等
JSON / Object动态 schema日志 / 半结构化实验性,生产慎用