尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FerretDB v1.14.0 技术解析:compact 命令落地与 insert 批量写入优化

FerretDB v1.14.0 技术解析:compact 命令落地与 insert 批量写入优化 后端数据库文档数据库【免费下载链接】FerretDBA truly Open Source MongoDB alternative项目地址https://gitcode.com/gh_mirrors/fe/FerretDB点击查看免费下载本篇指南围绕 FerretDB v1.14.0 版本的两个核心技术点展开全新实现的compact命令集合级存储整理与统计刷新和基于批量打包的insert写入性能优化。通过对照当前仓库中的命令注册表、Go 处理器与集成测试实现读者可以完整理解这两个特性的工作原理、调用链、参数语义与适用场景并掌握在真实集群中进行存储整理和批量写入的实战方法。版本背景新 PostgreSQL 后端全面接管v1.14.0 发布的核心前提是上一版本v1.13.0完成的 PostgreSQL 后端架构迁移。正如 v1.13.0 发布说明 所介绍FerretDB 采用基于 PostgreSQL 扩展documentdb的新后端架构而在 v1.14.0 中旧版 PostgreSQL 后端的代码已被完全移除代码库完成了彻底切换。这一架构演进的意义在于MongoDB 兼容层命令解析、BSON 处理、错误映射与存储执行层PostgreSQL 存储过程/函数得以清晰分离。从当前仓库的源码布局可以印证这一点internal/handler/目录下的msg_*.go文件负责解析 MongoDB wire 协议命令而internal/documentdb/目录下的documentdb_api、documentdb_api_internal、documentdb_core等包则通过 genwrap 生成的包装代码 调用 PostgreSQL 端的存储过程。v1.14.0 的compact命令正是在这套新后端之上实现的首批特性之一。对还不熟悉新架构的读者可以参考 v1.10 发布说明中的架构概述该版本首次引入 SQLite 后端并奠定了后端抽象基础再结合本文的源码级分析加深理解。新特性一compact 命令命令作用与语义compact是 MongoDB 中用于存储整理defragmentation的运维命令它会重组集合内部的物理数据布局、回收碎片空间并刷新集合的统计信息从而释放存储占用并提升后续查询与写入的效率。在 v1.14.0 中FerretDB 首次完整实现了该命令。命令在 命令注册表 中的登记信息明确描述了其职责compact: { handler: h.msgCompact, Help: Reduces the disk space collection takes and refreshes its statistics., },即减少集合占用的磁盘空间并刷新其统计信息。在 MongoDB 原生语义中compact通常对应存储引擎层面的VACUUM/ 碎片整理操作从 FerretDB 的集成测试注释中可以看到其 PostgreSQL 后端上的真实对应物// dont run in parallel as parallel VACUUM FULL ANALYZE may result in deadlock也就是说在 PostgreSQL 后端上compact对应一次VACUUM FULL ANALYZE操作这也是该测试刻意禁止并行的原因并行的 VACUUM FULL 可能引发死锁。使用方法与参数compact通过db.runCommand执行命令文档格式为// 对指定集合执行压缩整理 db.runCommand({ compact: collectionName, // 必填要整理的集合名称 force: true, // 可选即使存在其他活动连接也强制执行 })典型响应如下bytesFreed表示本次整理释放的字节数{ ok: 1, bytesFreed: number }参数语义说明参数类型必填说明compactstring是目标集合名称forceboolean否是否在存在活动连接时强制压缩源码级调用链当前仓库中compact命令的完整调用链为协议入口msg_compact.go 中的msgCompact处理器接收客户端请求文档req.Document()先通过h.s.CreateOrUpdateByLSID处理会话LSID上下文存储过程转发处理器通过连接池h.p.WithConn取得一个pgx.Conn将原始命令文档交给documentdb_api.CompactPostgreSQL 端执行由 genwrap 生成的包装函数 调用 PostgreSQL 端的documentdb_api.compact(p_spec bson)存储过程并把结果以 BSON 文档形式返回给客户端。func (h *Handler) msgCompact(connCtx context.Context, req *middleware.Request) (*middleware.Response, error) { doc : req.Document() if _, _, err : h.s.CreateOrUpdateByLSID(connCtx, doc); err ! nil { return nil, err } // ... err h.p.WithConn(func(conn *pgx.Conn) error { res, err documentdb_api.Compact(connCtx, conn, h.L, req.DocumentRaw()) return err }) // ... }可以看到整个命令从「命令解析」到「存储层执行」完全走新后端架构Go 侧只负责协议解析与错误包装实际的重组整理逻辑全部下沉到 PostgreSQL 存储过程documentdb_api.compact中执行最终通过SELECT compact::bytea FROM documentdb_api.compact($1::bytea)取回结果包装函数实现。错误处理与边界行为集成测试 commands_administration_test.go 对compact的正常路径与异常路径都做了覆盖正常路径TestCompactCommand先清空集合全部文档再执行{compact: collection, force: true}断言响应在移除bytesFreed键后与{ok: 1}完全一致异常路径TestCompactCommandNonExistent对不存在的数据库或集合执行compact断言返回 MongoDB 标准错误Code: 26Name: NamespaceNotFound消息为database does not exist/collection does not exist部分后端实现下可能为ns does not exist: db.collection。这套错误映射由internal/mongoerrors/包统一完成保证与 MongoDB 原生行为对齐。运维建议结合命令语义与后端实现在生产环境使用compact时需要注意执行时机建议在删除大量文档、数据文件出现明显膨胀后执行由于对应VACUUM FULL ANALYZE执行期间会重写表文件、占用较多 IO 并持有较重锁应避免在业务高峰期执行避免并发多个compact或与其他重量级维护操作并发可能触发死锁建议串行执行验证效果通过响应中的bytesFreed字段确认实际释放的空间量。新特性二insert 批量写入优化优化思路从逐条插入到批量打包v1.14.0 的第二个重要优化是insert命令的性能提升。优化前的实现是逐条插入文档一条文档对应一次后端调用优化后的做法是批量打包将一次insert命令携带的多条文档聚合为一次后端调用统一写入。对于 PostgreSQL 和 SQLite 两个后端该优化都统一生效。从当前仓库的代码可以清晰看到这一批量机制的落地形态。insert命令处理器 msg_insert.go 从 wire 消息中分离出**命令文档spec和文档序列seq**两个部分并一并交给后端存储过程func (h *Handler) msgInsert(connCtx context.Context, req *middleware.Request) (*middleware.Response, error) { doc, spec, seq, err : req.WireBody().(*wire.OpMsg).Sections() // ... err h.p.WithConn(func(conn *pgx.Conn) error { res, _, err documentdb_api.Insert(connCtx, conn, h.L, dbName, spec, seq) return err }) // ... return middleware.ResponseDoc(req, mongoerrors.MapWriteErrors(connCtx, res)) }而 PostgreSQL 端存储过程documentdb_api.insert的签名明确接收一个BSON 文档序列作为批量输入genwrap 生成签名// documentdb_api.insert(p_database_name text, p_insert documentdb_core.bson, // p_insert_documents documentdb_core.bsonsequence DEFAULT NULL, // OUT p_result documentdb_core.bson, OUT p_success boolean).关键点解读p_insert命令规范spec包含集合名、ordered等写入选项p_insert_documents类型为documentdb_core.bsonsequence的文档序列一次携带本次命令的所有待写入文档实现单次调用批量写入返回p_result结果 BSON含写入数量、错误列表与p_success是否成功。bsonsequence是 documentdb 扩展定义的 BSON 文档序列类型仓库中 documentdb_core.go 提供了一整套转换工具bson_to_bsonsequence、bsonsequence_from_bytea、bsonsequence_get_bson等支撑文档序列在 Go 与 PostgreSQL 之间的编码转换。批量写入的配套机制批量写入还需要处理部分失败的语义当批量中的某条文档写入失败时MongoDB 要求返回标准化的写错误Write Error结构。msgInsert末尾调用的mongoerrors.MapWriteErrors正是负责将 PostgreSQL 端返回的错误列表映射为 MongoDB 兼容的writeErrors结构保证批量场景下客户端仍能精确得知哪些文档失败、失败原因是什么。此外documentdb_api_internal.insert_worker签名见 documentdb_api_internal.go同样接收p_insert_internal_docs bsonsequence参数说明批量文档序列在底层 worker 层面也被直接复用避免了拆包再逐条下发的性能损耗。实践效果对于大批量数据导入、数据迁移、日志灌入等写密集场景批量插入可以显著减少客户端与服务器、服务器与 PostgreSQL 之间的往返次数RTT从而有效提升吞吐。使用 MongoDB 驱动时insertMany传入的文档数组天然对应一条批量insert命令可无缝享受该优化即使使用insert单条命令客户端驱动也会在ordered语义下尽可能合并请求。路线图预告capped collections除上述两个已完成特性外v1.14.0 发布时还预告了正在开发中的capped collections固定大小集合支持。capped collection 是 MongoDB 中一种有容量上限、自动淘汰最旧文档的集合类型常用于日志、事件流、缓存等场景。该功能在 v1.14.0 发布时尚未完成属于后续版本路线图内容使用时应以当前版本的实际支持情况为准。社区与生态进展v1.14.0 同时标志着开源社区的持续活跃新贡献者本版本迎来 3 位首次贡献者ShatilKhan、rubiagatra、gen1us2k并汇总了 Hacktoberfest 期间的大量合并请求云平台可用性FerretDB 在已有的 Civo、Scaleway 托管服务基础上正式登陆Vultr市场用户可以在更多云平台上以托管数据库形式使用兼容性承诺作为 MongoDB 的纯开源替代FerretDB 持续以「命令级兼容」为目标推进功能实现compact、批量insert等都是这一路线上的具体成果。总结FerretDB v1.14.0 是架构演进与工程优化并重的一个版本compact命令在新 PostgreSQL 后端上首次落地提供集合级存储整理与统计刷新能力Go 侧处理协议、PostgreSQL 存储过程负责执行对应VACUUM FULL ANALYZE并配备完整的错误映射与集成测试测试用例insert批量优化将逐条插入改为「文档序列一次下发」通过documentdb_api.insert(p_insert_documents bsonsequence)实现单次调用批量写入PostgreSQL 与 SQLite 后端统一受益并配套MapWriteErrors保证批量写错误语义架构层面旧 PostgreSQL 后端代码彻底移除新后端架构成为唯一实现路径为后续特性如 capped collections奠定了统一基础。对于希望深入阅读源码的读者建议从以下入口继续探索命令注册表 commands.go、compact 处理器 msg_compact.go、insert 处理器 msg_insert.go以及 genwrap 生成的存储过程包装代码 documentdb_api.go。赞分享后端数据库文档数据库【免费下载链接】FerretDBA truly Open Source MongoDB alternative项目地址https://gitcode.com/gh_mirrors/fe/FerretDB点击查看免费下载相关推荐Langfuse ClickHouse 写入最佳实践INSERT 批量大小10K–100K 行的原理与落地Langfuse ClickHouse 写入最佳实践INSERT 批量大小10K–100K 行的原理与落地 本篇基于 Langfuse 仓库内置的 Cli人工智能LLMOps可观测性AI 评测LLM 网关后端前端hello-sql数据写入INSERT、UPDATE与DELETE命令实战hello sql数据写入INSERT、UPDATE与DELETE命令实战 你是否在学习SQL时面对数据写入操作感到无从下手INSERT、UPDATE、D教程示例工程FerretDB Insert 操作完全指南insertOne 与 insertMany 深入解析FerretDB Insert 操作完全指南insertOne 与 insertMany 深入解析 本文以 FerretDB v2.5 文档中的 insert后端数据库文档数据库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表