【问题标题】:lmdb stores the data inefficiently?lmdb 存储数据效率低下?
【发布时间】:2020-11-28 01:34:13
【问题描述】:

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

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 的文件中,数据的结构如下(这里我展示了前 2 个蛋白质):

>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 倍。

【问题讨论】:

  • 为什么所有数据都用ascii展开,数据库会提升存储空间?
  • 请显示一些架构和原始数据的 sn-p。
  • 我已按要求添加了有关数据的其他信息。

标签: python deep-learning lmdb


【解决方案1】:

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

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

  • 数据处理在页面中(一般为4KB)
  • 每个“记录”需要存储额外的 b 树结构(用于键和数据)以及键和数据占用的页数

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-04
    相关资源
    最近更新 更多