序列化 vs 数据库

26

我认为保存应用程序状态的最佳方式是使用传统的关系型数据库,因为大多数情况下其表结构基本上代表了我们系统的数据模型+元数据。

然而,我的团队中的其他人认为,今天将整个对象图序列化为二进制或XML文件是最好的方法。
不需要说(但我还是要说)我们之间已经打起了世界大战,我希望听听您对这个问题的看法。

就个人而言,我讨厌序列化,因为:

  1. 所保存的数据仅适用于您的开发平台(在我的情况下是C#)。没有其他平台如Java或C++可以使用这些数据。
  2. 保存了整个对象图(包括所有继承链),而不仅仅是我们需要的数据。
  3. 更改数据模型可能会导致严重的向后兼容性问题,当尝试加载旧状态时。
  4. 在应用程序之间共享数据的部分是有问题的。

我想听听您对此的看法。

7个回答

22

您没有说明数据的类型--很大程度上取决于性能、并发性、安装、安全和可用性/集中化要求。

  • 如果这些数据非常大(例如,问题中的许多实例),数据库可以通过其索引功能提高性能。否则,它可能会损害性能,或者无法区分。

  • 如果您的应用程序同时由多个用户运行,并且他们可能想要编写此数据,则数据库有所帮助,因为您可以依靠事务来确保数据完整性。使用基于文件的持久性时,您必须自己处理。如果数据是单用户或单实例,则数据库很可能过度。

  • 如果您的应用程序具有自己的从头到尾的安装,则使用数据库会给用户增加额外的负担,用户必须设置和维护(应用修补程序等)数据库服务器。如果可以保证数据库可用并由其他人处理,则这不是一个问题。

  • 数据的安全要求是什么?如果数据是集中化的,并且有多个用户(无论是同时还是顺序),则可能需要管理数据的安全性和权限。看不到数据很难说是使用基于文件的持久性还是数据库更容易管理。

  • 如果数据仅限于本地,则关于数据的上述问题中的许多答案都指向基于文件的持久性。如果需要集中访问,则答案通常指向数据库。

我猜您可能不需要数据库,仅基于您主要从编程便利角度而非数据需求角度询问它的事实。特别是在.NET中,序列化高度可定制,并且可以轻松地定制以仅保留所需的基本部分。对于此数据的版本控制有众所周知的最佳实践,因此我不确定从这个角度来看,数据库方面是否有优势。
关于跨平台问题:如果您不能确定未来需要跨平台功能,请现在不要为其构建。当时机成熟(迁移等)时解决该问题几乎肯定更容易,而不是现在限制您的开发。往往情况下,YAGNI
关于在应用程序的各个部分之间共享数据:应将其架构化到应用程序本身中,例如,架构化到访问数据的类中。不要过载持久性机制,使其也成为应用程序各部分之间的数据传输通道;如果以这种方式过载它,则将持久化状态转变为跨对象合同,而不是适当地将其视为对象的私有状态的扩展。

8
当然,这取决于你想要序列化什么。在某些情况下,序列化非常容易。(我曾经用Java编写过一种时间轴程序,您可以在其中绘制、拖动和调整对象。如果您准备好了,可以将其保存在文件中(如myTimeline.til)。在那个时刻,数百个对象被保存,它们在画布上的位置、大小、颜色、内部文本、特殊效果等等。)
当然,您可以打开myTimeLine.til并继续工作。
所有这些只需要几行代码。(只需使所有类及其依赖项可序列化),我的编码时间不到5分钟,我自己都感到惊讶!(那是我第一次使用序列化)
在时间轴上工作时,您也可以“另存为”不同的版本,“til”文件非常容易备份和邮件发送。
因此,我的观点是:肯定有几种情况下数据库不是最佳解决方案。序列化并不是开发人员无聊时发明的。
  1. 如果使用XML序列化或SOAP,则不是真的。
  2. 不再很相关。
  3. 只有在您不小心的情况下,有很多“最佳实践”。
  4. 只有在您希望它成为问题时,才会出现问题,请参见1
当然,除了实现速度之外,序列化还有其他重要优点,例如在某些情况下根本不需要数据库!

3

请参考这篇Stackoverflow文章,了解XML和数据库管理系统的适用性评论。它讨论了一个与你们团队辩论主题非常相似的问题。


3

你提出了一些好的观点。我基本上同意你的看法,但我会扮演魔鬼的代言人。

  1. 如果需要,你可以编写一个C#转换器以后提取数据。

  2. 这是一个弱点,因为磁盘空间很便宜,我们使用的额外字节的成本远远低于我们将浪费的时间来尝试按照你的方式使所有内容工作。

  3. 这就是世界的方式。切断联系并要求升级。转换数据,或制作一个工具来完成,然后不再支持旧版本的做法。

  4. 如果C#程序将数据交给其他应用程序处理,那么其他应用程序不应该直接访问属于该应用程序的数据,对吧?


2

对于转移和离线存储,序列化是可以的;但对于活跃使用,某种类型的数据库要好得多。

通常(正如你所说),如果没有数据库,您需要反序列化整个流以执行任何查询,这使得扩展变得困难。加上线程等固有问题,您就会遇到麻烦。

关于序列化的一些其他问题并不都正确 - 只要明智地选择即可。显然,BinaryFormatter 对于可移植性和版本控制来说是一个糟糕的选择,但 "协议缓冲区"(Google 的序列化格式)具有 Java、C++、C#许多其他 版本,并设计为版本容忍型。


2

确保您有一个组件来处理与应用程序余下部分之间的干净接口的保存/加载状态。然后,您可以轻松地重新审视持久性的选择。

将对象图序列化为文件可能是一个不错的快速解决方案,非常快速实现。

但如果您开始遇到使数据库成为更好选择的问题,您可以插入新版本,而对应用程序的其余部分几乎没有影响。


0

是的,这可能是真的。缺点是你必须检索整个对象,就像从表中检索所有行一样。如果它很大,那么这将是一个缺点。但如果它不是很大,对于我的业余项目来说,它们并不是很大,那么它们也许是完美的匹配?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接