我正在运行许多非常慢的计算,并且具有可重用的结果(并且经常要计算新的内容依赖于之前已经执行过的计算)。为了使用它们,我想将结果存储在某个地方(永久)。可以通过两个标识符唯一地标识计算:实验名称和计算名称,其值是浮点数组(我目前将其存储为原始二进制数据)。需要经常按实验和计算名称分别访问(读取和写入)它们,有时还需要按实验名称(即,给定实验的所有计算及其结果)进行访问。它们有时也可以串联在一起,但是如果读写速度很快,则不需要为此操作提供额外的支持。无需为任何Web应用程序访问此数据(仅由需要计算结果的非生产脚本使用,但是每次都无法计算它们),并且不需要事务,但是每次写入都需要是原子的(例如,关闭计算机不应导致损坏/部分数据)。读取也必须是原子的(例如,如果两个进程试图访问一个计算的结果,但不存在,则其中一个开始保存新结果,另一个进程要么在完成后接收它,要么在接收任何结果时都不接收)所有)。不需要远程访问数据,但有帮助。
因此,TL; DR要求:
到目前为止,我尝试过的解决方案是:
自然地,在sqlite失败之后,第一个想法就是直接转移到像postgres这样的“适当”数据库,但是后来我意识到也许在这种情况下关系数据库并不是真正的解决之道(特别是因为速度至关重要在这里,并且我不需要它们的大多数功能)-特别是postgres可能不是要走的路,因为最接近Blob的是bytea,这需要额外的转化(因此可以确保性能受到关注)。但是,在对键值数据库进行了一些研究(这似乎适用于我的问题)之后,我发现我检查的所有数据库都不支持复合键,并且通常具有键的长度限制(例如,couchbase仅具有250个字节)。因此,我应该只使用普通的关系数据库,尝试NoSQL数据库之一,还是尝试完全不同的诸如HDF5的数据库?
答案 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更大的数据量),而当最终使用其中一个时,结果是是的。
以下设置(默认设置除外):
BLOB
BYTEA
(可悲地包括我所写的双重转换)< / li>
MEDIUMBLOB
如您所见,我能够自定义mysql得多,以适应手头的任务。下面的结果很好地反映了这一点:
sqlite postgres mysql
selects 90.816292 191.910514 106.363534
inserts 4367.483822 7227.473075 5081.281370
MySQL的速度与sqlite相似,而postgres的速度明显慢。