翻译自《leveldb》
LevelDB是一个快速的k-v存储库,由 Google开发,提供有序的字符串键值对映射.
特性
- Keys 和 values 可以使任意字节数组
- 数据按key排好序存储.
- 调用方可以提供比较函数来覆盖key的排序方式
- 基本操作有:
Put(key,value)
,Get(key)
,Delete(key)
. - 多个修改操作可以作为一个原子操作
- 用户可创建瞬时快照以获取一份一致的数据
- 支持对数据的前向和后向遍历.
- 数据使用 Snappy compression library 自动压缩.
- 通过虚拟接口与外部操作(文件系统操作等)对接,用户可以对操作系统的交互进行定制.
文档
LevelDB library documentation 有在线文档和源码.
局限性
- 这不是SQL(结构化)数据库. 没有关系型数据模型,不支持 SQL 查询, 不支持索引.
- 一个数据库同一时刻只能有一个进程(可能是多线程)访问.
- 库没有内置的客户端-服务器支持。需要此功能的应用得将此库封装到自己的服务器中.
源码获取
git clone --recurse-submodules https://github.com/google/leveldb.git
构建
此工程至此 CMake 构建
POSIX环境构建
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
(DCMAKE_BUILD_TYPE=Debug 可调式)
性能
这里是一份性能报告,来自 db_bench 程序的测试. 结果有些嘈杂,但也足以估计出性能.
准备
使用有100万个kv的数据库,每个key是16字节, value 是100字节. Values 压缩为原来一半大小.
LevelDB: version 1.1
Date: Sun May 1 12:11:26 2011
CPU: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
CPUCache: 4096 KB
Keys: 16 bytes each
Values: 100 bytes each (50 bytes after compression)
Entries: 1000000
Raw Size: 110.6 MB (estimated)
File Size: 62.9 MB (estimated)
写性能
顺序的或随机的"fill"操作将创建一个全新的数据库. "fillsync" 再每次写操作后将数据刷到磁盘中; 其余的写操作的数据会在操作系统缓存中保留一段时间. "overwrite" 对数据库中已有的key进行随机写操作.
fillseq : 1.765 micros/op; 62.7 MB/s
fillsync : 268.409 micros/op; 0.4 MB/s (10000 ops)
fillrandom : 2.460 micros/op; 45.0 MB/s
overwrite : 2.380 micros/op; 46.5 MB/s
以上每个操作对应单一kv的写操作。也就是随机写性能大概每秒 400,000 次写操作.
每个 "fillsync" 操作比磁盘定位(10ms)耗时更少(0.3毫秒). 可能是因为磁盘将更新缓存在内存中,并在写入盘片之前就返回响应了. 这个是否安全取决于硬盘在断电时是否有足够电量来保存硬盘内存数据.
读性能
这里列出了正向与反向按顺序读的性能, 也一并山治了随机查找的性能. 注意到这里的benchmark创建的数据库比较小. 因此这份报告给出的是leveldb对内存中的数据集操作的性能. 当读取一片不在操作系统缓冲区的数据时,耗时将由取到该数据需要的磁盘定位操作决定. 数据集是否能放入内存对写性能不会造成影响.
readrandom : 16.677 micros/op; (approximately 60,000 reads per second)
readseq : 0.476 micros/op; 232.3 MB/s
readreverse : 0.724 micros/op; 152.9 MB/s
LevelDB 在后台对内部存储数据进行压缩,以改善读性能。以上结果是在大量随机写操作后立刻进行的,压缩(通常会自动触发)后的结果更好.
readrandom : 11.602 micros/op; (approximately 85,000 reads per second)
readseq : 0.423 micros/op; 261.8 MB/s
readreverse : 0.663 micros/op; 166.9 MB/s
读操作的部分高耗时来自于对从磁盘读取的块的重复解压. 若能提供足够的缓存空间,levedb可以将解压后的块放在缓存中,读性能会进一步提升:
readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction)
readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction)
其他内容
更多解析详见:doc/index.md . 实现概览参考:doc/impl.md .
公共接口在 include/leveldb/*.h. 调用者不应 引用包内任何其他头文件,内部API可能会变更且没有提示性警告。.
头文件指引:
-
include/leveldb/db.h: DB的主要接口.
-
include/leveldb/options.h: 整个数据库的操作控制,读写操作的控制.
-
include/leveldb/comparator.h: 用户指定的比较函数的抽象接口. 若只需要按key的字节比较,可使用默认的比较函数;也可以自己编写比较函数来自定义排序方式 (例如处理不同的字符编码等.).
-
include/leveldb/iterator.h: 数据迭代的接口,可以从 DB 对象中获取迭代器.
-
include/leveldb/write_batch.h: 使用原子性的多重更新的接口.
-
include/leveldb/slice.h: 保存某个字节数组的地址和长度的简单模块.
-
include/leveldb/status.h: 多数公共接口都会返回 Status ,以获取成功或不同类型失败.
-
include/leveldb/env.h: 操作系统环境的抽象。posix 环境对应的实现在 util/env_posix.cc.
-
include/leveldb/table.h, include/leveldb/table_builder.h: 大多数客户端不太会直接用的底层模型.