我正在寻找一种快速(如巨大的性能,而不是快速修复)解决方案,用于持久化和检索数以千万计的小型(约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
答案 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 +树。 感谢