真实对比同一列国家代码用普通String和LowCardinality存储的压缩前后字节数,诚实说明真实收益点在哪里、以及本机小规模测试测不出什么。
代码CREATE TABLE demo.lctest ( k UInt64, country String, country_lc LowCardinality(String) ) ENGINE=MergeTree ORDER BY k; INSERT INTO demo.lctest SELECT number, ['CN','US','JP','DE','FR','IN','BR','RU','UK','CA'][(number%10)+1], ['CN','US','JP','DE','FR','IN','BR','RU','UK','CA'][(number%10)+1] FROM numbers(5000000);
column compressed uncompressed ratio country 228362 50000000 0.0046 country_lc 29223 5010027 0.0058 ← 压缩比反而略高于country 真实关键差异在uncompressed(压缩前)字节数: country 的 uncompressed = 50,000,000 字节 (500万行×平均10字节/字符串) country_lc 的 uncompressed = 5,010,027 字节 (真实只有前者的约十分之一)
如果只看最终压缩后的磁盘占用(228362 vs 29223字节),两者其实都小到可以忽略——因为LZ4对"只有10种取值、疯狂重复"的普通字符串本身就已经压缩得很彻底了。真正有意义的差异藏在data_uncompressed_bytes这一列:country_lc的压缩前体量真实只有country的约十分之一。
每一步都是本文上面用真实system.columns跑出来的原始结果。
system.columns(compressed/uncompressed对比)