首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >lmdb存储数据效率低下?

lmdb存储数据效率低下?
EN

Stack Overflow用户
提问于 2020-07-14 23:53:18
回答 1查看 438关注 0票数 1

我正在寻找一种能够快速读取随机数据样本以进行深度学习的数据文件结构,今天我一直在尝试使用lmdb。然而,有一件事似乎让我感到惊讶,那就是它似乎存储数据的效率如此之低。我有一个包含基因序列的大约120 GB的ASCII文件。现在,我希望能够将这些数据放入一个大小大致相同甚至更小的lmdb数据库中,因为ASCII是一种效率非常低的存储方法。然而,我所看到的似乎表明,我需要大约350 GB来将这些数据存储在一个lmdb文件中,而我只是不理解这一点。我是不是没有正确使用某些设置,或者我到底做错了什么?

代码语言:javascript
复制
import time
import lmdb
import pyarrow as pa

def dumps_pyarrow(obj):
    """
    Serialize an object.

    Returns:
        Implementation-dependent bytes-like object
    """
    return pa.serialize(obj).to_buffer()

t0 = time.time()
filepath = './../../Uniparc/uniparc_active/uniparc_active.fasta'
output_file = './../data/out_lmdb.fasta'
write_freq = 100000

start_line = 2
nprot = 0

db = lmdb.open(output_file, map_size=1e9, readonly=False,
               meminit=False, map_async=True)
txn = db.begin(write=True)
with open(filepath) as fp:
   line = fp.readline()
   cnt = 1
   protein = ''
   while line:
       if cnt >= start_line:
           if line[0] == '>': #Old protein finished, new protein starting on next line
               txn.put(u'{}'.format(nprot).encode('ascii'), dumps_pyarrow((protein)))
               nprot += 1
               if nprot % write_freq == 0:
                   t1 = time.time()
                   print("comitting... nprot={} ,time={:2.2f}".format(nprot,t1-t0))
                   txn.commit()
                   txn = db.begin(write=True)
                   line_checkpoint = cnt
               protein = ''
           else:
               protein += line.strip()
       line = fp.readline()
       cnt += 1


txn.commit()
keys = [u'{}'.format(k).encode('ascii') for k in range(nprot + 1)]
with db.begin(write=True) as txn:
    txn.put(b'__keys__', dumps_pyarrow(keys))
    txn.put(b'__len__', dumps_pyarrow(len(keys)))

print("Flushing database ...")
db.sync()
db.close()

t2 = time.time()
print("All done, time taken {:2.2f}s".format(t2-t0))

编辑:有关数据的一些附加信息:

在120 GB的文件中,数据的结构是这样的(这里我显示了前两个蛋白质):

代码语言:javascript
复制
>UPI00001E0F7B status=inactive
YPRSRSQQQGHHNAAQQAHHPYQLQHSASTVSHHPHAHGPPSQGGPGGPGPPHGGHPHHP
HHGGAGSGGGSGPGSHGGQPHHQKPRRTASQRIRAATAARKLHFVFDPAGRLCYYWSMVV
SMAFLYNFWVIIYRFAFQEINRRTIAIWFCLDYLSDFLYLIDILFHFRTGYLEDGVLQTD
ALKLRTHYMNSTIFYIDCLCLLPLDFLYLSIGFNSILRSFRLVKIYRFWAFMDRTERHTN
YPNLFRSTALIHYLLVIFHWNGCLYHIIHKNNGFGSRNWVYHDSESADVVKQYLQSYYWC
TLALTTIGDLPKPRSKGEYVFVILQLLFGLMLFATVLGHVANIVTSVSAARKEFQGESNL
RRQWVKVVWSAPASG
>UPI00001E0FBF status=active
MWRAQPSLWIWWIFLILVPSIRAVYEDYRLPRSVEPLHYNLRILTHLNSTDQRFEGSVTI
DLLARETTKNITLHAAYLKIDENRTSVVSGQEKFGVNRIEVNEVHNFYILHLGRELVKDQ
IYKLEMHFKAGLNDSQSGYYKSNYTDIVTKEVHHLAVTQFSPTFARQAFPCFDEPSWKAT
FNITLGYHKKYMGLSGMPVLRCQDHDSLTNYVWCDHDTLLRTSTYLVAFAVHDLENAATE
ESKTSNRVIFRNWMQPKLLGQEMISMEIAPKLLSFYENLFQINFPLAKVDQLTVPTHRFT
AMENWGLVTYNEERLPQNQGDYPQKQKDSTAFTVAHEYAHQWFGNLVTMNWWNDLWLKEG
PSTYFGYLALDSLQPEWRRGERFISRDLANFFSKDSNATVPAISKDVKNPAEVLGQFTEY
VYEKGSLTIRMLHKLVGEEAFFHGIRSFLERFSFGNVAQADLWNSLQMAALKNQVISSDF
NLSRAMDSWTLQGGYPLVTLIRNYKTGEVTLNQSRFFQEHGIEKASSCWWVPLRFVRQNL
PDFNQTTPQFWLECPLNTKVLKLPDHLSTDEWVILNPQVATIFRVNYDEHNWRLIIESLR
NDPNSGGIHKLNKAQLLDDLMALAAVRLHKYDKAFDLLEYLKKEQDFLPWQRAIGILNRL
GALLNVAEANKFKNYMQKLLLPLYNRFPKLSGIREAKPAIKDIPFAHFAYSQACRYHVAD
CTDQAKILAITHRTEGQLELPSDFQKVAYCSLLDEGGDAEFLEVFGLFQNSTNGSQRRIL
ASALGCVRNFGNFEQFLNYTLESDEKLLGDCYMLAVKSALNREPLVSPTANYIISHAKKL
GEKFKKKELTGLLLSLAQNLRSTEEIDRLKAQLEDLKEFEEPLKKALYQGKMNQKWQKDC
SSDFIEAIEKHL

当我将数据存储在数据库中时,我将组成每个蛋白质的所有行连接起来,并将它们存储为一个数据点。我忽略了标题(以>开头的行)。

我之所以相信数据在存储在数据库中时应该更压缩,是因为我希望它以某种二进制形式存储,我希望它会更压缩-尽管我承认我不知道它实际上是如何工作的(相比之下,压缩/压缩后的数据只有70 GB )。我可以接受lmdb格式的数据占用类似数量的空间,但我不明白为什么它占用的空间几乎是ASCII格式的3倍。

EN

回答 1

Stack Overflow用户

发布于 2020-11-28 01:34:14

LMDB不对数据实现任何类型的压缩。内存中的1Byte等于磁盘上的1Byte。

但它的内部结构可以放大所需的空间:

  • 数据处理是以页(通常为4KB)为单位的,每个“记录”都需要存储b-树的附加结构(用于键和数据)以及键和数据树( key

data )占用的页数

结论: LMDB是为快速数据访问而设计的,而不是为了节省空间。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62899075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档