【问题标题】:Sqlite appending data performance linear degradation, is this solvable?Sqlite追加数据性能线性下降,这个可以解决吗?
【发布时间】:2012-10-16 22:37:51
【问题描述】:

我有一个测试设置来将行写入数据库。 每个事务插入 10,000 行,没有更新。 每一步都比最后一步花费更长的线性时间。 前十个步骤花费了以下毫秒数来执行提交

568、772、942、1247、1717、1906、2268、2797、2922、3816、3945

到将 10,00 行添加到 500,000 行的表时,提交需要 37149 毫秒!

  • 我没有外键约束。

  • 我发现使用 WAL,提高了性能(给出了上图),但仍然是线性退化

  • PRAGMA Synchronous=OFF 无效

  • PRAGMAlocking_mode=EXCLUSIVE 无效

  • 在没有附加索引和附加索引的情况下运行。产生了大致恒定的时间差,因此仍然是线性退化。

我还有一些其他设置

  • setAutocommit(false)
  • PRAGMA page_size = 4096
  • PRAGMA journal_size_limit = 104857600
  • PRAGMA count_changes = 关闭
  • PRAGMA 缓存大小 = 10000
  • Schema 具有 Id INTEGER PRIMARY KEY ASC,其插入是增量的,由 Sqlite 生成

完整架构如下(我已经运行了有索引和没有索引,但都包含了)

create table if not exists [EventLog] (
Id INTEGER PRIMARY KEY ASC, 
DocumentId TEXT NOT NULL, 
Event TEXT NOT NULL, 
Content TEXT NOT NULL, 
TransactionId TEXT NOT NULL, 
Date INTEGER NOT NULL, 
User TEXT NOT NULL)

create index if not exists DocumentId ON EventLog (DocumentId)

create index if not exists TransactionId ON EventLog (TransactionId)

create index if not exists Date ON EventLog (Date)

这是使用在windows环境下运行的sqlite-jdbc-3.7.2

【问题讨论】:

  • 除了主键还有索引吗?
  • 尝试了附加索引并且没有
  • 请显示您的整个数据库架构(命令行工具中的.schema)。
  • 这是我的测试平台生成的架构,希望够用了,看看命令行工具
  • 你重新索引了吗? (不过,这与 sqlite 是否相关?)

标签: performance sqlite


【解决方案1】:

SQLite 表和索引are internally organized as B-Trees。在表中,Rowid 是排序键。 (您的 INTEGER PRIMARY KEY 是 Rowid。)


如果您插入的 ID 不大于表中已有的最大 ID,则不会附加记录,而是插入树中间的某个位置。当在一个事务中插入足够多的记录时,如果 ID 的分布是随机的,这意味着几乎数据库中的每一页都必须重写。

为了避免这种情况,

  1. 按升序插入 ID;或
  2. 将 ID 插入为NULL,以便 SQLite 选择下一个值;或
  3. 通过将 ID 字段声明为 INTEGER UNIQUE(如果您不需要额外的检查/索引,则仅声明为 INTEGER)来防止 SQLite 使用您的 ID 字段,从而使表排序独立于您的 ID。李>

在索引的情况下,插入具有随机分布的索引字段需要在随机位置更新索引。与表一样,当在一个事务中插入足够多的记录时,这意味着几乎索引中的每一页都必须重写。

当您加载大量数据时,建议在没有任何索引的情况下执行此操作,然后再重新创建它们。 (与其他一些数据库不同,SQLite 没有暂时禁用索引的功能;只需删除它们。)

【讨论】:

  • 感谢您的回答,不幸的是,情况已经如此,我已经相应地更新了我的问题
  • 我想,生成的 ids 和插入的数据,它们是递增的
  • 已更新;你有同样的问题,但有索引。
  • 我已经提取代码并验证它完全取决于索引,特别是在一行有自己的自定义 id(如 guid)的情况下
  • 我已经实现了一种删除并重新创建索引的方法,它仍然显示出线性退化,尽管速度较慢
【解决方案2】:

仅供参考,虽然我没有根据密钥的内容限制结构,但在 99.999% 的情况下,它将是一个指南。因此,为了解决性能问题,我刚刚编写了一个算法,用于使用前 8 个十六进制数字的基于时间的值生成顺序 guid。即使使用早期值生成 guid 块,这也非常有效。

【讨论】:

    猜你喜欢
    • 2020-03-07
    • 2020-01-14
    • 1970-01-01
    • 2012-08-10
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    相关资源
    最近更新 更多