https://github.com/sailist/dbrecord
前一段时间训练文本数据集,为了方便 shuffle 操作整出来的,这两天简单重构后分享一下。
主要特性:
用途:
感兴趣可以关注一下: https://github.com/sailist/dbrecord
1
Sailwww OP 补一条,sqlite 支持亿量级的数据低延迟索引读取,所以该库也有类似的性能表现,在一些场景下是替代 json 等数据格式的更好选择
|
2
BingoXuan 2022-03-14 14:07:13 +08:00
|
3
Shazoo 2022-03-14 16:20:24 +08:00
协程支持?多线程支持? multiprocess ?
|
4
Sailwww OP @BingoXuan 还真是,才发现有这个...对比了一下,基本确实是在重复造轮子,不过还是总结一下区别
- 在 io 上,因为我建的是双层索引,同时还有 id 自增列,所以在单值读取上慢了很多(但也在 1e-5 量级内,btw ,sqlitedict 是 1e-9 量级),数据库大小同量级下(因为索引)应该也大一些;优点是可以通过 list 的接口读取。 - 多值上它没有提供接口,在同时读取多个 key 或者 index 的场景下,我比他快 10 倍以上 - 整体上这个库算是一个 sqlite 小玩具,里面还提供了一个二分求数据库大小的函数,在无自增 id 缺失的情况下,比 select count(*) 要快 1000 倍左右 |
5
Sailwww OP @Shazoo
只有读操作支持,这个当初就是为了我读训练模型时候用的,没有多进程支持速度还是瓶颈...多线程和协程理应也支持?话说这个支持也就是 fork 的时候重建链接就可以了,也不需要别的操作.... 写操作这个是 sqlite 本身的问题,我没遇到使用场景,自己维护锁就没必要了 |
6
bnm965321 2022-03-15 09:59:15 +08:00
代码写的挺好的,不过我觉得这种场景不如使用 redis/leveldb
|
7
frinstioAKL 2022-03-16 11:29:20 +08:00
有趣, 问下楼主有试过和 lmdb 对比么
|
8
frinstioAKL 2022-03-16 11:37:47 +08:00
最近也考虑同样的场景需求, 正准备自己造轮子结果楼主已经先行一步了.
除了上面的和 lmdb 对比外, 楼主要不要试试把 pickle 序列化改成用 quickle?( https://github.com/jcrist/quickle) 看 stackoverflow, quickle 易用性和速度似乎是权衡比较好的 嘿嘿, 等楼主反馈结果(白嫖) |
9
Sailwww OP @bnm965321 多谢认可和建议,打算学一下 leveldb 的实现
@frinstioAKL lmdb 好像不能按 index 索引,是分块的吧?如果是 lmdb 的那种实现,不如尝试和 feather 格式对比(个人理解) quickle 试了一下,两个差的不多,quickle 读比 pickle 快 7% ,pickle 写比 quickle 快了 7% (有上下浮动),所以看具体使用场景吧。 我记得之前有哪个组做强化学习的,为了搞一个分布式系统开源了一个序列化的库好像效率更高,但我一时半会找不到了... |
10
Sailwww OP @frinstioAKL 哦抱歉,我记错了,不是分块读取的;我之前用过 lmdb ,不知道是不是之前代码写的烂的缘故,我记得 lmdb 单个文件数据存储,量级越大读起来就越慢...也是因为当初这件事,我后来尝试了 feather 格式,然后出来了这个库...
|
11
frinstioAKL 2022-03-16 16:14:49 +08:00
@Sailwww 谢谢反馈~ quickle 读写快 7% 感觉还是很可观, 写入速度我倒不是很在意. lmdb 量级越大读起来越慢, 请问你这边是遇到了多大的量级呢? 有空我也试试在我的使用场景下对比下, 试试你的库, 再反馈给你
|
12
Sailwww OP @frinstioAKL 我刚刚路上突然想到一点,我的测试可能有一定错误,因为我存的是数字,可能因为数据太小导致写入速度慢?(这种数据大小导致的某种均匀性我最初还是在 hash 方法里见到的)。我去看了 quickle 提供的 benchimark ,它在 dump 和 load 下好像都是有速度优势的。我看了 @BingoXuan 说的 sqlitedict 的实现,或许可以考虑直接提供一个 backend 参数传入..
lmdb 当初应该有一两百万了吧,忘了是纯文本场景还是文本图像混合场景了,哦对了 lmdb 里面有个 metadata 空间应该也有上限,当初我好像是用来放 label 的,这个也是弃掉的一个原因。 [随便找了一篇说明文档]( https://mozilla.github.io/firefox-browser-architecture/text/0015-rkv.html#:~:text=LMDB%20by%20default%20has%20a,may%20have%20performance%20impact%20too.) > LMDB by default has a maximum key size set as 512 bytes, there is a compile time configuration to change it, though a larger key may have performance impact too |
13
frinstioAKL 2022-03-16 18:21:15 +08:00
@Sailwww 受教了, lmdb 的 key 居然有大小限制, 这个我还真没超过这个限制过. 我这边存储 metadata 时一般加一个类似于 __labels__, __keys__ 这样的 key, 对应的 value 去存储实际的 label 等信息. 我这边几百万图片超过 500G LMDB 存储, 放 pytorch dataloader 里面暂时没遇到性能瓶颈. 基于 sqlite 的方案我倒是很想试试
|
14
Sailwww OP @frinstioAKL 似乎因为编解码方式的问题,图片的 sqlite 读取性能好像不是很客观,而且十分占空间,当时踩完坑后采取的是将图片保存成一个 chunk ,然后 sqlite 记录 chunk path 然后读。因为那段时间工期太赶没仔细测试,你可以再试验一下,我也等一波反馈~
|