【发布时间】:2011-10-26 08:34:10
【问题描述】:
我正在做一些性能比较,是对数据进行序列化还是将它们存储在数据库中。应用程序接收到大量数据 (x GB),需要以 18mb/s 的最低速度进行持久化(目前为止)
存储在 DB 中提供了更简单的功能,例如稍后搜索和访问数据、数据快照、数据迁移等,但我迄今为止的测试显示性能时间存在巨大差异。
测试保存了 1000 个对象(每个对象大约 700kb)。通过将它们保存为通用列表,将它们保存到表中的相应列或磁盘中。 (SQLite 最终得到更多数据)
- 保存到 SQLite v3,总大小 745mb:30.7 秒(~速度:24.3 mb/s)
- 序列化到磁盘,总大小 741mb:0.33 秒(~速度:2245 mb/s)
我没有对 SQLite 进行任何性能调整,只是将它与 Fluent nHibernate 和 SQLite.Data 适配器一起使用开箱即用(无事务),但起初认为这是一个巨大的差异。
显然,我知道通过 ORM 映射器和 DB 写入磁盘与序列化相比会产生开销,但这是很多。
还需要考虑的是在我收到数据时立即保存数据。如果出现电源故障,我需要最后收到的数据。
有什么想法吗?
-- 更新(我将继续研究解决方案)------
- 在事务中包装 1000 次插入的时间现在约为 14s = 53mb/s,但是如果我在中途抛出异常,我会丢失所有数据。
- 使用 IStatelessSession 似乎可以将时间缩短 0.5-1 秒
- 通过将 ID 分配给实体而不是在表中自动分配 ID 并因此摆脱每个插入 sql 的 (select row_generatedid()),没有看到任何性能提升。 -> Id(x => x.Id).GeneratedBy.Assigned();
- SQLite 中的 nosync() 替代方法不是替代方法,因为在电源故障的情况下数据库可能会损坏。
【问题讨论】:
-
你用 SQLite 尝试过 dapper 吗? code.google.com/p/dapper-dot-net - 另外,请确保在开始插入之前在 SQLite 上启动事务,如果每个插入都在其自己的隐式事务中运行,您将彻底扼杀性能。
-
至于开箱即用的解决方案,它运行隐含的是。不知道我是否可以以不同的方式运行它 - 数据需要立即保留,因为它被提供给我,如果我在电源故障期间丢失了等待提交的整个结果集,那将是很糟糕的。不过会测试它。
-
@Islandwind:然后考虑使用
INSERT OR [IGNORE]。 -
@AlixAxel 不太关注你?
-
@Islandwind:IGNORE 选项将导致 INSERT 不会失败,即使它实际上无法插入 - 可能是与事务结合使用的好解决方案,具体取决于您的错误处理策略。尽管如此,1000 个 INSERT 的 14 秒仍然是一个糟糕的性能......你确定瓶颈不是 ORM 吗?
标签: database performance sqlite serialization