SQLite vs序列化到磁盘

时间:2011-10-26 08:34:11

标签: database performance sqlite serialization

我正在进行一些性能比较,无论是序列化数据还是将它们存储在数据库中。该应用程序收到大量数据(x GB)的地狱,需要以最低18mb / s的速度保持持久性(现在)

存储在数据库中提供了以后搜索和访问数据,数据快照,数据迁移等方面的更简单的功能,但到目前为止我的测试显示了性能时间的巨大差异。

该测试可以保存1000个物体(每个物体约7个数千磅)。通过将它们保存为通用列表,将它们分别放到表中的各个列或磁盘上。 (SQLite最终会有更多数据)

  1. 保存到SQLite v3,总大小745mb:30.7秒(〜速度:24,3 mb / s)
  2. 序列化为磁盘,总大小741mb:0.33秒(〜速度:2245 mb / s)
  3. 我没有对SQLite进行任何性能调整,只需使用Fluent nHibernate和SQLite.Data适配器(没有事务),但最初认为这是一个巨大的差异。

    显然,我知道通过ORM映射器和DB写入磁盘会产生与序列化相比的开销,但这很多。

    另外考虑的是在收到数据时立即保留数据。如果出现电源故障,我需要收到最后一个数据。

    有什么想法吗?

    -----更新(我继续研究解决方案)------

    • 在一个事务中包装1000个插入时间现在是~14s = 53mb / s,但如果我中途抛出异常,我会丢失所有数据。
    • 使用IStatelessSession似乎可以将时间缩短0.5-1s
    • 通过将ID分配给实体而不是在表中自动分配并因此为每个插入sql删除(select row_generatedid()),没有看到任何性能提升。 - > Id(x => x.Id).GeneratedBy.Assigned();
    • SQLite中的nosync()替代方案不是替代方案,因为在发生电源故障时DB可能已损坏。

3 个答案:

答案 0 :(得分:5)

我有一次similar problem,我建议你去SQLite路线。

至于你的表现问题,我很确定你会得到一个非常显着的提升:

  1. 在单个事务中执行所有INSERT - 写入查询必须获取(并释放)对SQLite文件的锁定,这在磁盘I / O方面非常昂贵,您应该注意到huge boost ***
  2. 考虑使用多INSERT(由于您依赖ORM,这可能对您不起作用)
  3. 正如@ user896756所提到的,你也应该准备你的陈述

  4. 测试1:1000 INSERT

    CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
    INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
    INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
    ... 995 lines omitted
    INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
    INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
    INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');
    
    • PostgreSQL:4.373
    • MySQL:0.114
    • SQLite 2.7.6: 13.061
    • SQLite 2.7.6(nosync): 0.223

    测试2:事务中的25000个INSERT

    BEGIN;
    CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));
    INSERT INTO t2 VALUES(1,59672,'fifty nine thousand six hundred seventy two');
    ... 24997 lines omitted
    INSERT INTO t2 VALUES(24999,89569,'eighty nine thousand five hundred sixty nine');
    INSERT INTO t2 VALUES(25000,94666,'ninety four thousand six hundred sixty six');
    COMMIT;
    
    • PostgreSQL:4.900
    • MySQL:2.184
    • SQLite 2.7.6: 0.914
    • SQLite 2.7.6(nosync): 0.757

    ***这些基准测试适用于SQLite 2,SQLite 3 should be even faster

答案 1 :(得分:2)

您应该考虑为sqlite使用编译语句。

检查this

在插入/更新查询上有一个巨大的性能提升,我设法使用编译语句从2倍到10倍的执行时间获得,但从33秒到0.3秒是很长的路。

另一方面,SQLite的执行速度取决于您正在使用的表的模式,例如:如果您有大量数据的索引,则会导致插入缓慢。

答案 2 :(得分:0)

在进一步调查之后,答案对初始结果产生了一些混淆。

在使用更大的数据测试结果时,我得到了一些其他结果。

制造商将磁盘传输速率限制在126mb / s,如何在一瞬间写入750MB?不知道为什么。但是,当我快速降低到~136 mb / s时,我将数据量增加了传输速率。

对于数据库,使用具有大量数据(5-10GB)的IStatelessSession,使用事务我的速度高达90mb / s。这对我们的目的来说已经足够了,我确信它仍然可以通过编译的SQL语句和其他需要进行调整。