为何相同结构与索引的MongoDB集合比PostgreSQL表占用空间更大
MongoDB与PostgreSQL同结构同索引下的存储差异技术原因
- 底层数据模型的冗余开销差异
MongoDB是文档型数据库,采用BSON格式存储每条文档,即便所有文档结构完全一致,每条文档都会冗余存储所有字段名、字段类型标识;PostgreSQL作为关系型数据库,表的Schema元数据是全局统一存储的,每行数据仅存储实际字段值,无需重复存储字段名信息,这是两者存储开销差异最核心的来源。 - 索引存储实现差异
即便逻辑索引完全一致,两者的底层索引结构也存在开销差异:MongoDB WiredTiger引擎的索引项需要存储完整的文档主键/ObjectID,二级索引的关联开销更高;PostgreSQL的索引采用TID(元组标识符)关联堆表数据,标识长度更短,且默认的B树索引对重复值、有序值的压缩效率高于WiredTiger的默认前缀压缩策略。 - 预留空间与碎片管理策略差异
WiredTiger引擎默认会为集合做空间过度分配,预留部分闲置空间用于后续文档更新的就地写入,避免频繁页分裂,即便是新导入的无更新数据,也会有10%~20%的预留空间占用;PostgreSQL堆表默认不会提前预分配闲置空间,仅在产生删改死元组时才会出现碎片,新导入数据的碎片占比极低。你可以通过db.collection.stats().storageSize查看MongoDB集合的实际数据大小,和fileSize的差值就是预留的闲置空间;PostgreSQL可通过SELECT pg_total_relation_size('表名')查看实际总占用。 - 默认压缩策略差异
WiredTiger默认采用Snappy块压缩,压缩率约为30%50%;PostgreSQL默认对堆表采用pglz压缩,对TOAST存储的大字段采用更高效的压缩算法,相同数据量下压缩率通常比Snappy高5%15%。
如果需要降低MongoDB的存储占用,可以执行db.collection.runCommand({compact: '集合名'})释放闲置预留空间,也可以将WiredTiger的压缩策略调整为zstd进一步缩小存储占用。
内容的提问来源于stack exchange,提问作者xaroulis gekas
相关产品推荐
相关产品推荐

