最好的(免费)数据存储方式?如何更新文件系统?

时间:2020-03-06 14:48:38  来源:igfitidea点击:

我对如何解决此问题有一个想法,但我想知道我的问题是否有更简单,更易扩展的方法。

我正在使用的程序具有两种基本的数据形式:图像和与这些图像相关的信息。与图像相关的信息先前已存储在极其简单的JET数据库(四个表)中,事实证明,该数据库在存储字段中既缓慢又不完整。我们正在转向数据存储的新实现。考虑到所涉及的数据结构的简单性,我认为数据库是过大的。

每个图像将具有其自身的信息(捕获参数),将是一组相互关联的图像的一部分(例如在同一三十分钟内拍摄),然后又是一个较大的组的一部分(同一个人拍摄) )。现在,我将人们存储在具有唯一标识符的字典中。每个人都有一个不同图片组的列表,每个图片组都有一个图片组。所有这些类都是可序列化的,而我只是对字典进行序列化和反序列化。相当简单的东西。图像是分开存储的,因此字典的大小不会变成天文数字。

问题是:当我需要添加新的信息字段时会发生什么?是否有一种简便的方法来设置这些数据结构以应对将来的潜在修订?过去,我在C中处理此问题的方法是创建一个可序列化的结构,其中包含许多空字节(至少为k)以供将来扩展,该结构中的一个字节指示版本。然后,当程序读取该结构时,它将基于大量的switch语句知道要使用哪个反序列化(旧版本可以读取新数据,因为无关的数据只会进入被忽略的字段)。

C#中是否存在这样的方案?就像,如果我有一个包含一组String和Int对象的类,然后将另一个String对象添加到该结构中,如何从磁盘反序列化一个对象,然后向其中添加字符串?我是否需要辞职以拥有多个版本的数据类,并拥有一个采用反序列化流并根据存储在基类中的某些版本信息处理反序列化的工厂?还是像Dictionary这样的类是用于存储此类信息的理想选择,因为它会自动反序列化磁盘上的所有字段,并且如果添加了新字段,我就可以捕获异常并用空白的Strings和Ints替换那些值?

如果我采用字典方法,是否会与文件读/写以及参数检索时间相关联的速度飞快?我认为如果一个类中只有字段,那么字段检索是即时的,但是在字典中,与该类相关的开销很小。

谢谢!

解决方案

Sqlite是我们想要的。这是一个快速,可嵌入的单文件数据库,具有对大多数语言的绑定。

关于可扩展性,我们可以使用默认属性存储模型,然后为属性扩展提供单独的表以供将来更改。

一两年后,如果代码仍在使用中,我们将很高兴1)其他开发人员将不必学习自定义代码结构来维护代码,2)我们可以导出,查看,修改使用标准的数据库工具(有一个用于sqlite文件的ODBC驱动程序和各种查询工具)来处理数据,以及3)我们将能够通过最少的代码更改就可以扩展到数据库。

有一个数据库模式,我不记得它的名称,可以处理这种情况。我们基本上有两个表。一个表存储变量名,另一个表存储变量值。如果要对变量进行分组,请添加第三个表,该表与变量名称表具有一对多关系。此设置的优点是,我们可以继续添加不同的变量,而不必不断更改数据库模式。在与经常改变主意的部门打交道时(例如市场部)节省了我的培根很多次。

唯一的缺点是变量值表将需要将实际值存储为字符串列(实际上是varchar或者nvarchar)。然后,我们必须处理将值转换回其本机表示形式的麻烦。我目前维护这样的东西。变量表目前大约有8亿行。它仍然相当快,因为​​我仍然可以在一秒钟之内检索到某些值的变化。

此刻我的大脑不知所措,所以我不确定我可以建议还是反对数据库,但是如果我们正在寻找与版本无关的序列化,那么至少不要检查协议缓冲区就是一个傻瓜。

这是我了解的C#/。NET实现的快速列表:

  • 原始网
  • 原型#
  • jskeet的dotnet-protobufs

我不是Cprogrammer,但我喜欢mmap()调用,并且看到有一个项目正在为C#做这样的事情。

见Mmap

Structured files are very performing if tailored for a specific application but are difficult to manage and an hardly reusable code resource. A better solution is a virtual memory-like implementation.
  
  
  Up to 4 gigabyte of information can be managed.
  Space can be optimized to real data size.
  All the data can be viewed as a single array and accessed with read/write operations.
  No needing to structure to store but just use and store.
  Can be cached.
  Is highly reusable.

因此,使用sqllite的原因如下:
1.我们不需要每次都从磁盘读取/写入整个数据库
2.即使开始时没有保留足够的占位符,添加起来也要容易得多
3.更轻松地根据我们想要的内容进行搜索
4.更容易以超出设计应用程序的方式更改数据

字典方法的问题
1.除非我们制作了智能词典,否则每次都需要读/写整个数据库(除非我们仔细设计数据结构,否则很难保持向后兼容性)
---- a)如果我们没有留下足够的位置,再见
2.似乎我们必须线性搜索所有照片才能在"捕获属性"之一上进行搜索
3.图片可以在多个组中吗?一张图片可以容纳一个以上的人吗?两个人可以在同一个小组中吗?有了字典,这些事情就会变得毛茸茸。

对于数据库表,如果获得新属性,则可以说"更改表图片添加属性数据类型"。然后,只要我们不制定规则来规定该属性必须具有值,就仍然可以加载和保存较旧的版本。同时,较新的版本可以使用新的属性。

另外,我们不需要将图片保存在数据库中。我们可以只将图片的路径存储在数据库中。然后,当应用程序需要图片时,只需从磁盘文件中加载即可。这样可以使数据库大小更小。而且,与加载映像的时间相比,获取磁盘文件的额外查找时间很可能是微不足道的。

可能桌子应该是
图片(PictureID,GroupID ?、文件路径,捕获参数1,捕获参数2等。)

如果我们想获得更大的灵活性,可以制作一张桌子
CaptureParameter(PictureID,ParameterName,ParameterValue)...我建议不要这样做,因为它比仅将它们放在一个表中要低得多(更不用说检索/搜索"捕获参数"的查询会更复杂)。

Person(PersonID,任何人的属性,例如名称/等等)
组(GroupID,组名,PersonID?)
PersonGroup?(PersonID,GroupID)
PictureGroup?(GroupID,PictureID)

只是一句警告,SQLLite,协议缓冲区,mmap等都很好,但是我们应该对每个实现进行原型设计和测试,并确保我们不会遇到相同的性能问题或者不同的瓶颈。

简单性可能只是为了升级到SQL(Express)(我们可能会对性能提高感到惊讶)并修复当前数据库设计中缺少的所有内容。然后,如果仍然存在性能问题,那就开始研究这些其他技术。