如何处理 MySQL 中 auto_increment ID 列的碎片

Posted

技术标签:

【中文标题】如何处理 MySQL 中 auto_increment ID 列的碎片【英文标题】:How to handle fragmentation of auto_increment ID column in MySQL 【发布时间】:2010-12-21 22:17:48 【问题描述】:

我有一个带有 auto_increment 字段的表,有时行会被删除,因此 auto_increment 会留下空白。有没有办法避免这种情况,或者如果没有,至少,如何编写一个 SQL 查询:

    auto_increment 值更改为最大值(当前值)+ 1 返回新的auto_increment 值?

我知道如何编写 12 部分,但我可以将它们放在同一个查询中吗?

如果不可能:

如何“选择”(返回)auto_increment 值或auto_increment 值 + 1?

【问题讨论】:

您应该始终指定您正在使用的数据库系统,例如在这种情况下是 mysql 抱歉,感谢您告诉我。 【参考方案1】:

重新编号会造成混乱。现有报告将引用记录 99,但如果系统重新编号,它可能会将该记录重新编号为 98,现在所有报告(和填充的 UI)都是错误的。一旦分配了唯一 ID,它就必须保持不变。

将 ID 字段用于除简单唯一编号之外的任何内容都会有问题。要求“无间隙”与能够删除的要求完全不一致。也许您可以将记录标记为已删除而不是删除它们。那么就真的没有缝隙了。假设您正在制作带编号的发票:您将拥有一张带有该编号的零值已取消发票,而不是删除它。

【讨论】:

【参考方案2】:

正如 djna 在她/他的回答中所说,以这种方式更改数据库表不是一个好习惯,如果您一直在选择正确的方案和数据,也没有必要这样做类型。顺便说一下你的问题:

我有一个带有 auto_increment 字段的表,有时行会被删除,因此 auto_increment 会留下空白。有什么办法可以避免吗?

    如果您的表在其自动增量列中有太多间隙,可能是由于太多测试INSERT 查询的结果 如果您想通过消除间隙来防止过多的 id 值 如果id 列只是一个计数器,与数据库中的任何其他列都没有关系

,这可能是您(或任何其他正在寻找此类东西的人)正在寻找的东西:

解决方案

    删除原来的id列 使用auto_increment on 再次添加

但如果您只想将auto_increment 重置为第一个可用值:

ALTER TABLE `table_name` AUTO_INCREMENT=1

【讨论】:

【参考方案3】:

我通常同意此页面上的智者(以及duplicate 问题)建议不要重复使用自动递增的 ID。这是一个很好的建议,但我认为提出这个问题的对错不应该由我们来决定,让我们假设开发人员知道他们想要做什么以及为什么。

答案是,正如 Travis J 所说,您可以通过在插入语句中包含 id 列并分配您想要的特定值来重用自动增量 id。

这里有一点需要使用扳手:MySQL 本身(至少 5.6 InnoDB)在以下情况下重用自动增量 ID:

删除具有最高自动增量 ID 的任意行数 停止和启动 MySQL 插入新行

插入的行的 id 计算为 max(id)+1,它确实从被删除的 id 继续。

【讨论】:

【参考方案4】:

即使在 autoinc 表中,也有一种手动插入 id 的方法。您所要做的就是找出丢失的 ID。

但是,不要这样做。如果您的数据库是关系型的,那可能会非常危险。删除的 id 可能在其他地方使用过。删除后,它不会造成太大问题,也许它会孤立记录。如果被替换,它会带来一个巨大的问题,因为会出现错误的关系。

假设我有一张汽车桌和一张人桌

car
carid
ownerid
name

person
personid
name

还有一些简单的数据

car
1 1 Van
2 1 Truck
3 2 Car
4 3 Ferrari
5 4 Pinto

person
1 Mike
2 Joe
3 John
4 Steve

现在我删除了 John。

person
1 Mike
2 Joe
4 Steve

如果我在表中添加了一个新人 Jim,并且他得到了一个填补空白的 id,那么他最终会得到 id 3

1 Mike
2 Joe
3 Jim
4 Steve

按关系来说,他是法拉利的车主。

【讨论】:

【参考方案5】:

不确定这是否会有所帮助,但在 sql server 中,您可以重新设定身份字段。似乎在 mySql 中有一个 ALTER TABLE 语句来实现这一点。例如,将 id 设置为在 59446 处继续。

ALTER TABLE table_name AUTO_INCREMENT = 59446; 

我想你应该可以结合一个查询来获取auto_increment字段的最大值,然后根据需要使用alter table进行更新。

【讨论】:

以上是关于如何处理 MySQL 中 auto_increment ID 列的碎片的主要内容,如果未能解决你的问题,请参考以下文章

如何处理 mySQL 中未来孤立记录的删除

如何处理 MySQL 数据库中的大量数据?

MySQL 如何处理查询中的 ORDER BY 和 LIMIT?

Mysql如何处理重复数据?让你的效率更高效

在MYSQL中将日期转换为日期范围---如何处理日期中的间隙

mySQL 如何处理 ORDER BY 中的动态值