sqlite INTEGER PRIMARY KEY具有高插入成本

xytpbqjk  于 12个月前  发布在  SQLite
关注(0)|答案(1)|浏览(113)

编辑:我原来的帖子是错误的;问题仅仅是工作集大小和随机访问导致大量页面被访问。
在更大的测试范围内,二次模型出现分歧,变得更加线性。此外,我犯了一个错误,并认为我已经排除了随机插入顺序作为原因,但该配置是错误的,单调插入确实更快。
This graph shows the behavior of different column types.
测试设置:

  • SQLite版本:2022-01-06
  • 语言:C++。
  • 测试数据:唯一的32位整数的连续序列,混洗。
  • 插入方法:预处理查询,10万事务批处理,每条语句20行,带绑定参数
  • PRAGMAs:安全默认值,具有独占锁定模式和内存临时存储。
  • DB:本地文件系统上的空白测试数据库,NVMe SSD

测试的变化:

1. CREATE TABLE integers (value INTEGER);
2. CREATE TABLE integers (value INTEGER PRIMARY KEY);
3. CREATE TABLE integers (value INTEGER PRIMARY KEY) WITHOUT ROWID;
4. CREATE TABLE integers (value INT PRIMARY KEY);

近似拟合曲线:

1:   Linear:     0             + 2.5E-7 * N
2+3: Quadratic:  1.35E-7 * N^2 + 1.8E-6 * N
4:   Quadratic:  1.35E-7 * N^2 + 3.7E-6 * N

我期望从INTEGER表(1)到INTEGER PRIMARY KEYWITHOUT ROWID(2,3),这应该更快,因为值和rowid列的合并提供了更好的页面使用。令我惊讶的是,使用任何一种形式的cripples插入性能与二次成本项,最终变得不可用。(版本2和版本3的性能是相同的,因为我相信它们指定了相同的东西。
版本(4)演示了相同的行为,但具有两倍的线性成本组件,反映了INT PRIMARY KEYINTEGER PK不同的特殊情况,并导致除了聚集表之外的辅助索引插入。我认为主键慢是一个特殊的问题,只在使用WITHOUT ROWID行为时才会发生,但是将约束移动到二级索引并不能解决这个问题。

lvjbypge

lvjbypge1#

二次成本是由于混洗插入。
Sqlite表和索引存储在Btree结构中。
表(1)有一个隐藏的ROWID列和value列。每个新记录都添加到表的末尾,在同一页中,并带有递增的ROWID。除了偶尔的Btree重新平衡之外,页面读取和写入保持在最低限度。
表(2)和表(3)是相同的:ROWID不存在,而value是表的键,这意味着表实际上是聚集在值列上。如果你按顺序插入这些值,你会有和(1)中一样的性能,但是以随机顺序插入它们会导致对许多不同页面的持续访问,不仅需要查找,而且需要更频繁地更新Btree。
表(4)与表(1)相同,但是由于value被声明为PRIMARY KEY,因此value上的索引被自动创建和维护。所以你有顺序更新表的线性成本(如(1))加上随机更新Btree索引的成本(如(2))。

相关问题