同一份数据用 snappy、zstd、zlib 存,分别占多少磁盘?压缩有没有拖慢写入和扫描?这篇给每个集合指定不同的 block_compressor,用同一份 10 万条日志样的数据对比,再换成随机字节看压缩什么时候无效。
样例: {'_id': 0, 'user': 3307, 'level': 'ERROR', 'ts': 1700000000, 'msg': 'xqmb oyjmxz nplvptva fshvmj aan ajhnmri …', 'host': 'srv-33'}10 万条日志样的文档(约 19.8 MB BSON),放进 4 个集合,createCollection 时用 storageEngine.wiredTiger.configString 指定 block_compressor。
压缩算法 dataSize storageSize 占 BSON 的比例 磁盘文件大小 none 19,784,644 20,647,936 104% 20,647,936 snappy 19,784,644 9,158,656 46% 9,158,656 zstd 19,784,644 6,217,728 31% 6,217,728 zlib 19,784,644 6,934,528 35% 6,934,528
none 比原始数据还多 4%(页面开销);snappy 压到 46%,zstd 31%,zlib 35%。
c_snappy: block_compressor=snappy
c_zstd: block_compressor=zstd
test> db.adminCommand({getCmdLineOpts: 1}).parsed
{
net: {
bindIp: '127.0.0.1',
port: 9901,
unixDomainSocket: { enabled: false }
},
storage: {
dbPath: '/data/m8/db',
wiredTiger: { engineConfig: { cacheSizeGB: 0.25 } }
},
systemLog: {
destination: 'file',
path: '/data/m8/mongod.log'
}
}
没有指定压缩算法的集合 c_default: block_compressor=snappy
索引的 creationString 里有 prefix_compression 吗: block_compressor=,prefix_compression=true,prefix_compression_min=4不指定时集合用 snappy;索引不用块压缩,用前缀压缩(prefix_compression=true)。
none 247 ms snappy 242 ms zstd 260 ms zlib 274 ms
插入 10 万个文档,四种算法都在 242~274 ms,差别不大。
none 45 ms (3 次: 47, 36, 45) snappy 37 ms (3 次: 37, 33, 45) zstd 91 ms (3 次: 81, 91, 92) zlib 88 ms (3 次: 92, 87, 88)
清空 WiredTiger 缓存后全表扫描:snappy 与 none 接近,zstd 和 zlib 约慢一倍,因为解压更耗 CPU。
随机字节文档的 BSON 总大小 22,200,000; none storageSize 23,040,000 占 BSON 的 104% snappy storageSize 22,925,312 占 BSON 的 103% zstd storageSize 22,642,688 占 BSON 的 102% zlib storageSize 22,646,784 占 BSON 的 102%
随机字节本身不可压缩,所有算法下都接近原始大小。压缩收益取决于数据重复程度,上线前要用自己的数据测。