py-lmdb:Python 操作 LMDB 的高性能方案

py-lmdb 在 GitHub 上拿到了 743 个 Star。

LMDB 是 OpenLDAP 项目里孵化出来的嵌入式键值数据库,全称 Lightning Memory-Mapped Database。内存映射、B+ 树索引、事务完整、零拷贝读取——这几个特性组合在一起,让它在读密集场景下比 SQLite 快一个数量级。py-lmdb 是它的 Python 绑定,也是社区公认最成熟的方案。

1、LMDB 能做什么

一句话:本地嵌入式数据库,不需要单独的服务进程,数据直接映射到内存页,读操作不走系统调用。

配置文件本地缓存、ML 训练样本的快速加载、边缘设备上的持久化存储——这些场景对延迟极度敏感、不希望依赖网络服务、数据规模又不至于上分布式,LMDB 正好匹配。它的写入是序列化的,天然避免了锁竞争;读操作完全无锁,多线程并发读取性能不衰减。

py-lmdb 目前支持 Python 3.9 及以上版本和 PyPy。项目维护了相当长时间,早期版本曾一路兼容到 Python 2.5,最后一个支持 Python 2.7 的版本是 1.4.1。

正文顶部截图

2、py-lmdb 做了什么

LMDB 是 C 写的,Python 调用需要一层胶水。py-lmdb 不只是简单的 ctypes 包装,它把 LMDB 的事务模型映射成了 Python 的上下文管理器,游标操作用迭代器模式暴露,字节流自动处理编码解码。

核心体验两个词:Pythonic、零拷贝。读数据不需要反序列化开销,从 LMDB 读出来的内存 buffer 可以直接交给 numpy 或者 Pillow 消费。对于处理大量二进制数据的场景,这一层优化远比 API 好不好看重要。

3、使用方式

import lmdb

env = lmdb.open('/tmp/test', map_size=10485760)

with env.begin(write=True) as txn:
    txn.put(b'key', b'value')

with env.begin() as txn:
    value = txn.get(b'key')
    print(value)

API 清爽直接。事务用 with 语句自动提交或回滚,游标遍历用 Python 迭代器,跟操作普通 dict 体感差不多。

map_size 是唯一需要留意的参数,它设置了内存映射文件的最大尺寸,需要在打开环境时指定,之后不能动态调整。给一个合理上限即可,LMDB 不会立即占用那么多磁盘空间,是按需增长的。

README区域截图

4、哪些场景适合

  • 需要高性能本地 KV 存储的 Python 后端应用
  • ML 训练管线中频繁读取样本、对延迟极其敏感的环节
  • 嵌入式设备上需要零运维零配置的持久化方案
  • 不需要 SQL 复杂查询、只做键值读写的任何场景

不适合的场景也很明确:需要复杂条件查询、需要跨网络多客户端访问、写负载远大于读负载。这些情况,传统关系数据库或 Redis 更合适。

条件查询、需要跨网络多客户端访问、写负载远大于读负载。这些情况,传统关系数据库或 Redis 更合适。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐