我有一个测试设置来将行写入数据库.
每个事务都插入10,000行,没有更新.
每个步骤的线性时间比最后一个长.
前十个步骤在ms中花费了以下时间来执行提交
568,772,942,1247,1717,1906,2268,2797,2922,3816,3945
当它向500,000行的表中添加10,00行时,需要37149 ms才能提交!
>我没有外键约束.
>我发现使用WAL,提高性能(给出上面的数字),但仍然线性降级
> PRAGMA Synchronous = OFF无效
> PRAGMA locking_mode = EXCLUSIVE无效
>没有其他索引和其他索引.造成大致恒定的时差,因此仍然是线性退化.
我有一些其他设置
> setAutocommit(false)
> PRAGMA page_size = 4096
> PRAGMA journal_size_limit = 104857600
> PRAGMA count_changes = OFF
> PRAGMA cache_size = 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
最佳答案 SQLite表和索引
are internally organized as B-Trees.在表中,Rowid是排序键. (你的INTEGER PRIMARY KEY是Rowid.)
如果插入的ID不大于表中已有的最大ID,则不会附加记录,而是插入树中间的某个位置.在一个事务中插入足够的记录时,如果ID的分布是随机的,这意味着必须重写数据库中的几乎每个页面.
要避免这种情况,
>按递增顺序插入ID;要么
>将ID插入为NULL,以便SQLite选择下一个值;要么
>通过将其声明为INTEGER UNIQUE(或者如果您不需要额外的检查/索引只是INTEGER),防止SQLite将您的ID字段用作Rowid,从而使表的排序与您的ID无关.
在索引的情况下,插入具有随机分布的索引字段需要在随机位置更新索引.与表一样,在一个事务中插入足够的记录时,这意味着必须重写索引中的几乎每个页面.
当您加载大量数据时,建议在没有任何索引的情况下执行此操作,然后再重新创建它们. (与其他一些数据库不同,SQLite没有暂时禁用索引的功能;只需删除它们.)