存储和访问大量相对较小的文件

时间:2018-10-09 13:28:55

标签: database performance storage

我正在运行许多非常慢的计算,并且具有可重用的结果(并且经常要计算新的内容依赖于之前已经执行过的计算)。为了使用它们,我想将结果存储在某个地方(永久)。可以通过两个标识符唯一地标识计算:实验名称和计算名称,其值是浮点数组(我目前将其存储为原始二进制数据)。需要经常按实验和计算名称分别访问(读取和写入)它们,有时还需要按实验名称(即,给定实验的所有计算及其结果)进行访问。它们有时也可以串联在一起,但是如果读写速度很快,则不需要为此操作提供额外的支持。无需为任何Web应用程序访问此数据(仅由需要计算结果的非生产脚本使用,但是每次都无法计算它们),并且不需要事务,但是每次写入都需要是原子的(例如,关闭计算机不应导致损坏/部分数据)。读取也必须是原子的(例如,如果两个进程试图访问一个计算的结果,但不存在,则其中一个开始保存新结果,另一个进程要么在完成后接收它,要么在接收任何结果时都不接收)所有)。不需要远程访问数据,但有帮助。

因此,TL; DR要求:

  • 永久存储二进制数据(无需存储除标识符以外的其他元数据)
  • 基于复合标识符的非常快速的访问(读/写)
  • 通过复合标识符的一部分读取所有数据的能力
  • 并行,原子读/写
  • 无需交易,复杂的查询等。
  • 可以使用远程访问,但不是必需的
  • 整个过程都可以节省时间,因此速度至关重要

到目前为止,我尝试过的解决方案是:

  • 将它们存储为单独的文件(每个实验一个目录,每个计算一个二进制文件)-需要手动处理原子性,而且大多数文件系统支持的文件名最多只能包含255个字符(并且计算名称可能比该名称更长) ),因此需要附加的映射;我也不确定ext4(这是我正在使用并且不能更改的文件系统)是否旨在处理数百万个文件
  • 使用sqlite数据库(只有一个表和一个复合主键)-最初看起来很完美,但是当我们获得数百GB的数据(数百万个〜100 KB Blob,以及它们及其数目大小会增加),即使应用了互联网上的优化功能,它也开始变得缓慢

自然地,在sqlite失败之后,第一个想法就是直接转移到像postgres这样的“适当”数据库,但是后来我意识到也许在这种情况下关系数据库并不是真正的解决之道(特别是因为速度至关重要在这里,并且我不需要它们的大多数功能)-特别是postgres可能不是要走的路,因为最接近Blob的是bytea,这需要额外的转化(因此可以确保性能受到关注)。但是,在对键值数据库进行了一些研究(这似乎适用于我的问题)之后,我发现我检查的所有数据库都不支持复合键,并且通常具有键的长度限制(例如,couchbase仅具有250个字节)。因此,我应该只使用普通的关系数据库,尝试NoSQL数据库之一,还是尝试完全不同的诸如HDF5的数据库?

2 个答案:

答案 0 :(得分:1)

一种改进数据库解决方案的方法是外部化数据块。

您可以将SeaweedFS https://github.com/chrislusf/seaweedfs用作对象存储,上传blob并获取文件ID,然后将文件ID存储在数据库中。 (我正在研究SeaweedFS)

这将大大减轻数据库的负载,并且查询会更快。

答案 1 :(得分:0)

因此,无论如何,我最终还是使用了关系数据库(因为只有在那里,我才能使用复合键而不会受到任何黑客攻击)。 我执行了一个基准测试,将sqlite与postgres和mysql进行了比较-约60 KB blob插入了500 000个插入,然后按整个键进行了500000个选择。这不足以将sqlite减慢到我正在经历的不可接受的水平,但是设置了一个参考点(即,sqlite运行的速度很少,这对于我来说是可以接受的)。我以为在使用mysql和postgres添加更多记录时,我不会受到太大的性能影响(因为它们被设计为处理比sqlite更大的数据量),而当最终使用其中一个时,结果是是的。

以下设置(默认设置除外):

  • sqlite:日志模式= wal(并行访问所需),隔离级别自动提交,值为BLOB
  • postgres:隔离级别自动提交(无法关闭事务,并且在一个巨大的事务中完成所有操作对我来说不是一种选择),值为BYTEA(可悲地包括我所写的双重转换)< / li>
  • mysql:engine = aria,交易已禁用,值为MEDIUMBLOB

如您所见,我能够自定义mysql得多,以适应手头的任务。下面的结果很好地反映了这一点:

                     sqlite     postgres        mysql
selects           90.816292   191.910514   106.363534
inserts         4367.483822  7227.473075  5081.281370

MySQL的速度与sqlite相似,而postgres的速度明显慢。