如何处理 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
值?
我知道如何编写 1 和 2 部分,但我可以将它们放在同一个查询中吗?
如果不可能:
如何“选择”(返回)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 如何处理查询中的 ORDER BY 和 LIMIT?