检索/存储数百万个小二进制对象的最快方法

时间:2009-07-18 17:47:59

标签: .net database performance sqlite data-structures

我正在寻找一种快速(如巨大的性能,而不是快速修复)解决方案,用于持久化和检索数以千万计的小型(约1k)二进制对象。每个对象应具有唯一的ID以供检索(最好是GUID或SHA)。其他要求是它应该可以从.NET使用,它不需要额外的软件安装。

目前,我正在使用一个带有单个表的SQLite数据库来完成这项工作,但我想摆脱处理简单SQL指令的开销,例如SELECT data FROM store WHERE id = id。

我还测试了NTFS下的直接文件系统持久性,但是一旦达到数千万个对象,性能就会迅速降低。

P.S。顺便说一句,永远不需要删除对象,插入率非常非常低。实际上,每次对象更改时,都会存储新版本,并保留以前的版本。这实际上是支持时间旅行的要求。

只需在此主题中添加一些其他信息:

BLOB或不BLOB:数据库或文件系统中的大对象存储http://arxiv.org/abs/cs.DB/0701168

10 个答案:

答案 0 :(得分:10)

您可以通过将对象的GUID标识符分解为多个部分并将它们用作目录名来减轻NTFS的性能问题。这样,每个目录只包含有限数量的子目录或文件。

e.g。如果标识符为aaaa-bb-cc-ddddeeee,则项目的路径为c:\store\aaaa\bbcc\dddd\eeee.dat,将每个目录限制为不超过64k子项。

答案 1 :(得分:1)

每个语句只需调用prepare函数一次,参数表示为按?(所以SELECT data FROM store WHERE id=?是您准备的声明);然后你做的“数百万次”只是将bind参数放到准备好的语句中并调用sqlite_step - 这些都是快速操作。如果blob open可能不会更快,那么值得进行基准测试。 IOW,我建议坚持使用SQLite并深入挖掘它的低级接口(如果必须,可以使用托管C ++)以获得最佳性能 - 它真的是一个非常棒的小引擎,而且它的性能常常让我感到惊讶!

答案 2 :(得分:0)

我认为数据库查询是您最好的选择。

数据库的整个结构仅适用于这种情况,解析和优化简单查询几乎无法实现。

您可以制定一个方案,将大blob中的所有对象直接存储到文件系统,然后在其上打开内存映射文件视图,并将对象ID索引到blob中,但我怀疑你会看到比DB更多的性能,因为这基本上就是它的作用。

答案 3 :(得分:0)

存储[Guid - >的单独索引(另一个文件)文件号+文件中的偏移量]。使用二进制搜索进行检索,并在文件n达到特定大小时移至文件n + 1。索引文件中的每一行只有24个字节(固定大小:guid +文件号+偏移量,分割文件为4GB),排序速度很快(插入排序速度很慢。)

编辑:您有非常简单的要求,可以直接进行优化。这个精心构建的系统应该胜过数据库,特别是如果你小心数据的块读取和异步IO。数据库查询将始终具有解析的开销。

编辑2:如果您也需要它安全(总是一个好主意),请看一下这里有关file system transactions概念如何帮助您防弹的说明。

答案 4 :(得分:0)

您是否考虑过试用对象数据库,例如db4o?它可以持久化任何CLR objekt,并使用查询语言快速访问它们(支持LINQ!)。我没有数百万个对象,但只有几千个访问速度相当快,与具有索引id字段的类似SQL查询没有重大区别。

答案 5 :(得分:0)

固定大小块大约2k的二进制文件怎么样,前4个字节是对象的长度...

对象i的位置为i * 2048字节,然后读取对象的2048字节,从前4个字节(无符号)获取实际对象的长度。

答案 6 :(得分:0)

我喜欢Earwicker的解决方案。我处理这个的方式非常相似。

我做的是:

假设您的指南是3F2504E0-4F89-11D3-9A0C-0305E82C3301。

将guid哈希到三个字母的哈希值。 AAA-ZZZ。

为了论证,假设你的guid哈希到“xap”。

您的信息可以在文件c:\ store \ x \ xa \ xap \ 3F2504E04F8911D39A0C0305E82C3301.dat中找到

当然,这种策略有很多变种。例如,xap可以是一个文件,其中所有二进制对象都附加在一起,带有标题或外部文件,其中包含guid和偏移量。

答案 7 :(得分:0)

您可以检查HDF5结构是否适合您的任务

答案 8 :(得分:0)

我倾向于同意亚历克斯,如果你编写自己的解决方案,你正在重新发明已经可能在SQLite中的东西,但如果你必须......

你可以在这里做一个BTree工作。它是任何数据库的主力,你的问题空间并不是那么糟糕。数以百万计的1k对象仍然只有10亿个字节,所以该文件可由操作系统管理,并且有很多BTree示例可供尝试。

与使用文件系统目录结构相比,基本上使用真正的BTree创建BTree模拟将会更快。

另一个可能感兴趣的解决方案是Mogilfs,它是一个分布式冗余文件系统。

答案 9 :(得分:0)

我不知道SQLite是否支持索引,但如果确实如此,那么你可以通过在ID字段上创建索引来加快速度。

如果没有,那么你最好的选择是B +树。 感谢