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

时间:2008-09-26 21:32:38

标签: c# extensibility data-storage

我知道如何解决这个问题,但我想知道我的问题是否更简单,更易于扩展。

我正在处理的程序有两种基本形式的数据:图像和与这些图像相关的信息。与图像相关联的信息先前已存储在极其简单的JET数据库(四个表)中,这在存储的字段中变得既慢又不完整。我们正在转向数据存储的新实现。鉴于所涉及的数据结构简单,我认为数据库过度。

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

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

C#中是否存在这样的方案?就像,如果我有一个类是一组String和Int对象的类,然后我将另一个String对象添加到结构中,我如何从磁盘反序列化一个对象,然后将字符串添加到它?我是否需要让自己拥有多个版本的数据类,以及一个采用反序列化流并根据存储在基类中的某些版本信息处理反序列化的工厂?或者是类似于字典的类,非常适合存储此类信息,因为它会自动反序列化磁盘上的所有字段,如果添加了新字段,我可以捕获异常并在空白字符串和Int中替换这些值?

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

谢谢!

6 个答案:

答案 0 :(得分:2)

Sqlite就是你想要的。它是一个快速,可嵌入的单文件数据库,可以绑定大多数语言。

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

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

答案 1 :(得分:2)

只是一个小小的警告,SQLLite,Protocol Buffers,mmap等...都非常好,但你应该对每个实现进行原型设计和测试,并确保你不会遇到相同的性能问题或不同的瓶颈。 / p>

简单性可能只是升级到SQL(Express)(您可能会对性能增益感到惊讶)并修复当前数据库设计中缺少的内容。然后,如果仍然是一个问题,开始调查这些其他技术。

答案 2 :(得分:1)

有一个数据库模式,我无法记住这个名称,可以处理这种情况。你基本上有两张桌子。一个表存储变量名,另一个表存储变量值。如果要对变量进行分组,则添加与变量名称表具有一对多关系的第三个表。此设置的优点是可以让您继续添加不同的变量,而无需不断更改数据库架构。在与经常改变主意的部门(如市场营销部门)打交道时,节省了我的培根几次。

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

答案 3 :(得分:1)

我的大脑现在已经被炒了,所以我不确定我是否可以建议或反对数据库,但是如果你正在寻找与版本无关的序列化,你至少要检查一下你是个傻瓜。 Protocol Buffers

以下是我对C#/ .NET的了解的快速列表:

答案 4 :(得分:1)

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

请参阅Mmap

  

如果为特定应用程序量身定制但结构化文件非常有效,但难以管理且难以重复使用的代码资源。更好的解决方案是虚拟内存式实现。

     
      
  • 最多可以管理4千兆字节的信息。
  •   
  • 可以根据实际数据大小优化空间。
  •   
  • 可以将所有数据视为单个数组,并通过读/写操作进行访问。
  •   
  • 无需构建存储,只需使用和存储。
  •   
  • 可以缓存。   是高度可重用的。
  •   

答案 5 :(得分:0)

因此,请使用sqllite,原因如下:
1.您不需要每次都从磁盘读取/写入整个数据库 2.即使你没有在开头留下足够的占位符,也容易添加 3.更容易根据您想要的任何内容进行搜索 4.更容易以超出应用程序设计的方式更改数据

字典方法的问题
1.除非你制作了智能字典,否则每次都需要读/写整个数据库(除非你仔细设计数据结构,否则很难保持向后兼容性)
----- a)如果你没有留下足够的占位符再见 2.看起来好像你必须对所有照片进行线性搜索才能搜索其中一个捕获属性 3.图片可以在多个组中吗?一张照片可以不止一个人吗?两个人可以在同一组吗?对于词典,这些东西会变得毛茸茸......

使用数据库表,如果获得新属性,则可以说Alter Table Picture Add Attribute DataType。然后,只要您不规定属性必须具有值,您仍然可以加载和保存旧版本。同时,较新的版本可以使用新属性。

此外,您无需将图片保存在数据库中。您可以只存储数据库中图片的路径。然后,当应用程序需要图片时,只需从磁盘文件加载它。这使数据库大小更小。与加载图像的时间相比,获取磁盘文件的额外搜索时间很可能是微不足道的。

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

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

Person(PersonID,Name / Etc等任何人物属性)
组(GroupID,Group Name,PersonID?)
PersonGroup?(PersonID,GroupID)
PictureGroup?(GroupID,PictureID)