4

我对如何解决这个问题有一个想法,但我想知道是否有更容易和更可扩展的东西来解决我的问题。

我正在开发的程序有两种基本形式的数据:图像,以及与这些图像相关的信息。与图像相关的信息以前存储在一个极其简单的 JET 数据库(四个表)中,结果证明存储的字段既慢又不完整。我们正在转向数据存储的新实施。考虑到所涉及的数据结构的简单性,我认为数据库是多余的。

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

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

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

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

谢谢!

4

6 回答 6

2

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

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

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

于 2008-09-26T21:39:41.917 回答
2

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

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

于 2008-09-27T00:28:08.983 回答
1

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

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

于 2008-09-26T21:45:08.470 回答
1

此刻我的大脑被炸了,所以我不确定我是否可以建议支持或反对数据库,但如果您正在寻找与版本无关的序列化,那么至少不检查Protocol Buffers将是一个傻瓜。

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

于 2008-09-26T21:49:45.573 回答
1

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

地图

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

  • 最多可以管理 4 GB 的信息。
  • 空间可以优化为实际数据大小。
  • 所有数据都可以视为一个数组,并通过读/写操作进行访问。
  • 无需构建存储,只需使用和存储。
  • 可以缓存。高度可重用。
于 2008-09-26T21:50:24.887 回答
0

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

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

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

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

可能你的表应该是
Picture(PictureID, GroupID?, File Path, Capture Parameter 1, Capture Parameter 2, etc..)

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

Person(PersonID, Any Person Attributes like Name/Etc.)
Group(GroupID, Group Name, PersonID?)
PersonGroup?(PersonID, GroupID)
PictureGroup?(GroupID, PictureID)

于 2008-09-26T22:40:06.107 回答