JSON 列类型从 ClickHouse 25.3+ 开始已可用于生产环境。不建议在生产环境中使用更早的版本。
快速决策
- 如果每个字段都有已知且稳定的类型,并且 schema 很少变动 → 类型化列
- 如果大多数字段都是稳定的,但某一部分是动态的或不可预测的 → 混合方案 (类型化列 + JSON)
- 如果整个结构都是动态的,并且键会在不同记录之间出现或消失 → 原生 JSON 列
- 如果动态字段是键值对,且值类型一致 (例如字符串标签、数值指标)
→ 选择
Map而不是 JSON - 如果你只是存储和读取 JSON blob,而不进行字段级查询 → 不透明 String 存储
不要混淆 JSON format 和 JSON column type。你可以将 JSON 格式的数据 (通过
JSONEachRow 等) 插入到类型化列中,而完全不使用 JSON 列类型。这里要做的选择是列类型,而不是输入格式。方法说明
类型化列
Array、Tuple 和 Nested 类型来表示。
权衡取舍: schema 变更需要执行 ALTER TABLE。如果不更新 schema,插入时出现的额外字段会被静默丢弃。
设置、验证与注意事项
设置、验证与注意事项
设置验证注意事项
- 如果你使用
JSONEachRow插入 JSON 数据,而 JSON 中包含 schema 里不存在的字段,ClickHouse 默认会静默丢弃这些字段。如果你希望改为报错,请将input_format_skip_unknown_fields设置为0。
混合方案 (类型化列 + JSON)
设置、验证与注意事项
设置、验证与注意事项
设置验证注意事项
- 对于你预先已知的 JSON 路径,请使用 类型提示。类型提示会绕过判别列,并将该路径像普通类型化列一样存储,具有相同性能且没有额外开销。
- 对于你永远不会查询的路径 (如调试元数据、内部追踪 ID) ,使用
SKIP或SKIP REGEXP可以节省存储并减少子列数量。 - 将
max_dynamic_paths设置为与你实际查询的不同路径数量相匹配。默认值 (1024) 适用于大多数场景。如果动态部分较少,可以适当调低。 - 不要将
max_dynamic_paths设为高于 10,000。较高的值会增加资源消耗并降低效率。
带点号的键默认情况下,带点号的键 (例如
http.status_code) 会被视为嵌套路径,因此 {"http.status_code": 200} 的存储方式与 {"http": {"status_code": 200}} 相同。这在 OTel 属性中很常见。可以使用类型提示来控制带点路径的存储方式,或者启用 json_type_escape_dots_in_keys (25.8+) 。原生 JSON 列
不透明 String 存储
JSONExtract 系列) ,就无法进行字段级查询;而这种做法在大规模场景下会比较慢。
设置、验证和注意事项
设置、验证和注意事项
设置验证注意事项
- 如果需求发生变化,后续需要字段级查询,就得使用类型化列或 JSON 列新建一张表,再对数据进行回填。如果你有任何可能需要查询单个字段的情况,建议一开始就改用混合方案。
JSONExtract函数会在每次查询时解析字符串。用于临时探索还可以,但不适合生产环境中的仪表盘或高 QPS 工作负载。- 如果 JSON 载荷较大,可考虑对 String 列使用压缩编解码器 (
ZSTD) ——它的压缩效果很好。
对比
何时更适合使用 Map
Map(String, T) 会比 JSON 列更简单、更高效。常见示例包括:字符串标签 (Map(String, String)) 、数值指标 (Map(String, Float64)) 和功能开关 (Map(String, Bool)) 。
Map 支持键级筛选 (tags['env'] = 'prod') ,存储成本低于 JSON,并且避免了 JSON 类型的子列开销。请注意,默认情况下,按键查找会线性扫描整个 Map——对于较小的标签集这完全没问题,但如果 Map 包含 100+ 个键,建议考虑使用with_buckets serialization。当值包含混合类型或结构存在嵌套时,请使用 JSON;当数据是扁平的键值对且值类型统一时,请使用 Map。
- 在适当情况下使用 JSON — 何时使用 JSON 列类型而非其他方案
- JSON 数据类型参考 — 类型提示、SKIP、max_dynamic_paths 和内部信息函数的完整语法
- 选择数据类型 — 数据类型选择的一般指导
- A New Powerful JSON Data Type for ClickHouse — 深入解析 JSON 类型的存储架构
- JSON 格式参考 — JSON 数据的输入/输出格式 (JSONEachRow、JSONAsObject 等)