真实插入两条结构不同的JSON文档到原生JSON类型列,验证字段查询的便利性,并用columns_substreams.txt揭示背后真实惊人的物理存储复杂度。
代码CREATE TABLE demo.jsontest (k UInt64, doc JSON) ENGINE=MergeTree ORDER BY k; INSERT INTO demo.jsontest VALUES (1, '{"name":"alice","age":30,"tags":["a","b"]}'); INSERT INTO demo.jsontest VALUES (2, '{"name":"bob","score":9.5}'); -- 结构完全不同 SELECT k, doc.name, doc.age, doc.score FROM demo.jsontest ORDER BY k;
SELECT k, doc.name, doc.age, doc.score FROM demo.jsontest ORDER BY k; → 1 alice 30 \N ← 第1行没有score字段,真实自动是NULL 2 bob \N 9.5 ← 第2行没有age字段,真实自动是NULL
不需要写JSONExtract,doc.name/doc.age这种点号路径真实就能直接当成表的普通列来查询——缺失的字段真实自动补NULL,不需要额外处理。
47 substreams for column `doc`: doc.object_structure doc.age.dynamic_structure doc.age.variant_discr_prefix doc.age.variant_discr doc.age.Int64 doc.age.SharedVariant.size doc.age.SharedVariant doc.name.dynamic_structure doc.name.variant_discr_prefix doc.name.variant_discr doc.name.String.size doc.name.String doc.tags.Array%28Nullable%28String%29%29.size0 ... doc.object_shared_data.0.size0 doc.object_shared_data.0%2Epaths doc.object_shared_data.0%2Evalues doc.object_shared_data.1.size0 ...(一直到 .7,共8组)
每一步都是本文上面用真实原生JSON类型跑出来的原始结果。
JSON 类型(非String+JSONExtract)columns_substreams.txt 揭示JSON列的物理拆分结构