【问题标题】:Storing and accessing a large number of relatively small files存储和访问大量相对较小的文件
【发布时间】:2018-10-09 13:28:55
【问题描述】:

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

所以,TL;DR 要求:

  • 二进制数据的永久存储(不需要存储标识符以外的元数据)
  • 基于复合标识符的快速访问(读/写)
  • 能够通过复合标识符的一部分读取所有数据
  • 并发、原子读/写
  • 无需事务、复杂查询等。
  • 远程访问很不错,但不是必需的
  • 整个过程主要是为了节省时间,所以速度很关键

目前我尝试的解决方案是:

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

当然,在 sqlite 失败后,第一个想法就是转移到像 postgres 这样的“适当”数据库,但后来我意识到,在这种情况下,关系数据库可能并不是真正要走的路(尤其是因为速度很关键在这里,我不需要它们的大部分功能)-尤其是 postgres 可能不是要走的路,因为最接近 blob 的是 bytea,它需要额外的转换(因此可以保证性能命中)。然而,在研究了一些关于键值数据库(这似乎适用于我的问题)之后,我发现我检查的所有数据库都不支持复合键,并且通常对键有长度限制(例如,couchbase 刚刚250 字节)。那么,我应该只使用普通的关系数据库,尝试使用 NoSQL 数据库之一,还是像 HDF5 这样完全不同的数据库?

【问题讨论】:

    标签: database performance storage


    【解决方案1】:

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

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

    这应该会大大减少数据库负载,并且查询会更快。

    【讨论】:

      【解决方案2】:

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

      设置(默认值除外)如下:

      • sqlite:日志模式=wal(并行访问需要),隔离级别自动提交,值为BLOB
      • postgres:隔离级别自动提交(无法关闭事务,并且在一个巨大的事务中做所有事情对我来说不是一个选项),值为BYTEA(很遗憾,其中包括我写的双重转换)
      • 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 的速度要慢得多。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-16
        • 2012-10-05
        • 1970-01-01
        • 2012-11-10
        • 1970-01-01
        • 2023-03-05
        • 2011-03-14
        相关资源
        最近更新 更多