存储系统
了解 Meilisearch 如何在其 LMDB 存储引擎中存储和处理数据。
Meilisearch 在很多方面都是一个数据库:它存储索引文档以及返回相关搜索结果所需的数据。
数据库位置
Meilisearch 会在您首次启动实例时创建数据库。默认情况下,您可以在与 meilisearch
二进制文件相同目录下的 data.ms
文件夹中找到它。
数据库位置可能会因多种因素而改变,例如您是否使用 --db-path
实例选项 配置了不同的数据库路径,或者您是否使用了像 Docker 这样的操作系统虚拟化工具。
LMDB
从零开始创建和管理数据库是一项艰巨的工作。重新发明轮子毫无意义,因此 Meilisearch 底层使用了存储引擎。这使得 Meilisearch 团队能够专注于提升搜索相关性和搜索性能,同时将复杂的文档创建、读取和更新任务(无论是在磁盘还是内存中)抽象化。
我们使用的存储引擎名为 Lightning Memory-Mapped Database(简称 LMDB)。LMDB 是一个用 C 语言编写的具有 ACID 特性的事务型键值存储,最初为 OpenLDAP 开发。虽然我们也考虑过其他选项,如 Sled 和 RocksDB,但最终选择了 LMDB,因为它为我们提供了性能、稳定性和功能的最佳组合。
内存映射
LMDB 将其数据存储在内存映射文件中。所有从 LMDB 获取的数据都直接从内存映射返回,这意味着在数据获取过程中不会发生内存分配或内存复制。
当 Meilisearch 请求文档时,所有存储在磁盘上的文档都会自动加载到内存中。这确保 LMDB 始终能充分利用可用 RAM 来检索文档。
为了获得最佳性能,建议提供与数据库在磁盘上占用空间相同大小的 RAM,这样所有数据结构都能装入内存。
理解 LMDB
选择 LMDB 会带来某些优缺点,特别是在数据库大小和内存使用方面。我们在此总结 LMDB 最重要的特性,但更深入的信息请查看LMDB 开发者的这篇博客文章。
数据库大小
当从 Meilisearch 索引中删除文档时,您可能会注意到磁盘空间使用量保持不变。这是因为 LMDB 在内部将该空间标记为空闲,但不会使其对整个操作系统可用。这种设计选择带来了更好的性能,因为不需要定期进行压缩操作。因此,LMDB(以及 Meilisearch)占用的磁盘空间往往会随着时间的推移而增加。无法精确计算 Meilisearch 实例可能占用的最大空间量。
内存使用
由于 LMDB 采用内存映射技术,实际分配给 Meilisearch 的内存(或不分配)是由操作系统管理的。
因此,如果您在服务器上以独立程序运行 Meilisearch,LMDB 会尽可能使用最大可用 RAM。一般来说,为了获得最佳性能,您应该配备与 Meilisearch 占用磁盘空间相同大小的内存。
另一方面,如果您同时运行 Meilisearch 和其他程序,操作系统会根据各程序的需求管理内存。这使得 Meilisearch 在开发环境中的内存使用非常灵活。
实测磁盘使用量
以下测量数据基于 movies.json 数据集,这是一个 8.6 MB 的 JSON 文件,包含 19,553 个文档。
索引完成后,LMDB 中的数据集大小约为 122MB。
原始 JSON | Meilisearch 数据库磁盘占用 | 内存使用量 | 虚拟内存使用量 |
---|---|---|---|
9.1 MB | 224 MB | ≃ 305 MB | 205 Gb (内存映射) |
这意味着数据库使用了 305 MB 内存和 224 MB 磁盘空间。请注意 虚拟内存 仅指计算机为 Meilisearch 分配的磁盘空间——并不表示数据库实际使用了这些空间。详见内存使用部分。
这些指标高度依赖于运行 Meilisearch 的机器配置。在性能明显不足的机器上运行此测试可能会得到不同的结果。
需要特别注意的是:没有可靠的方法能预测数据库的最终大小。这对市面上几乎所有搜索引擎都适用——我们只是唯一公开说明这一点的。
数据库大小受众多因素影响,包括设置、相关性规则、分面功能的使用、支持的语言数量等等。