SQLite:Autoincrement和insert或ignore将产生未使用的Autoincrement Keys

时间:2017-11-05 10:52:32

标签: sql sqlite

我使用带有自动递增ID和邮件地址的表Mail。该表用于其他4个表中,主要用于保存存储空间(String只保存一次而不是4次)。我使用INSERT OR IGNORE只是盲目地将邮件地址添加到表中,如果存在则忽略更新。这种方法比使用SELECT ...检查存在要快得多,并在需要时执行INSERT

对于每个INSERT OR IGNORE自动递增,无论是否被忽略或完成,自动递增Id都会递增。我跑了一次我约。 500k数据集继续进行。因此,每次运行后,最后一个自动增量键增加500k。我知道有2 ^ 63-1个可能的键,所以很长时间才能使用它们。

我也试过了INSERT OR REPLACE,但这会在每次运行命令时增加数据集的Id,所以这根本不是解决方案。

有没有办法阻止每个INSERT OR IGNORE增加自动增量键?

表邮件示例(替换为伪地址)
    mIdMail   mMail
    "1"       ""
    "7"       "mail1@example.com"
    "15"      "mail2@example.com"
    "17"      "mail3@example.com"
    "19"      "mail4@example.com"
    "23"      "mail5@example.com"
    ...
插入查询(使用Java Lib:org.apache.commons.dbutils)
    INSERT OR IGNORE 
    INTO MAIL 
    ( mMail  ) 
    VALUES ( ? );
表定义
    CREATE TABLE IF NOT EXISTS MAIL (
       mIdMail          INTEGER PRIMARY KEY AUTOINCREMENT, 
       mMail            CHAR(90) UNIQUE 
    ); 

2 个答案:

答案 0 :(得分:3)

要获得无间隙的自动增量值,请删除AUTOINCREMENT关键字。 (是的,你get autoincrementing values even without it。)

答案 1 :(得分:1)

自动增量键的行为与它们的具体行为相同,因为数据库保证了它们的行为 - 无论并发事务和事务失败。

自动增量键有两个保证:

  • 它们正在增加,因此后来的插入值比之前的插入值更大。
  • 保证它们是独一无二的。

分配密钥的机制并不能保证没有间隙。为什么不?因为无间隙会在数据库上产生更多的开销。基本上,表上的每个事务都需要在下一个事务发生之前完全序列化(完成并提交)。一般来说,从绩效角度来看,这是一个非常糟糕的主意。

不幸的是,SQLite没有最简单的解决方案,只需在自动递增的密钥上调用row_number()即可。您可以尝试使用触发器实现无间隙自动增量,从而显着降低应用程序的速度。

我真正的建议只是忍受差距。接受他们。投降。这就是内置方法的工作方式,并且有充分的理由。现在设计数据库/应用程序的其余部分,牢记这一点。