为什么不永久删除PRIMARY_KEY?

时间:2014-02-27 13:55:00

标签: mysql sql database

如果我在数据库中有一个表,并且有一个包含AUTO_INCREMENTPRIMARY_KEY列的表。

假设表中总共有 5行。

现在考虑这种情况......

我删除了5行。

下次我INSERT行时,它会有PRIMARY_KEY 6

为什么删除的记录的密钥也不会被永久删除?

如果那些人一直认识到针对该密钥存储了什么记录,我们怎么知道那条记录是什么记录,因为它被删除了。

4 个答案:

答案 0 :(得分:1)

主键是行的唯一标识符。它们不应该被回收利用。

考虑插入ID为“123”的用户的情况,然后有人删除该记录,然后插入新记录。 RDBMS会回收ID。

然后你回来寻找ID为“123”的用户,当然你会得到其他用户,而不是你想要的用户。

听起来像是完整性约束和实体完整性的问题。

答案 1 :(得分:0)

这是真的。 auto_increment总是最后一个值+ 1。 您可以更改auto_increment的当前值,但不能定义较低的值。

有关更多信息,请阅读此主题: Changing the current count of an Auto Increment value in MySQL?

问题的另一个解决方案是通过我们的主键定义主键:

INSERT tableName (id, field1, field2) VALUES((SELECT COUNT(*) + 1 FROM tableName),"value1","value2")

答案 2 :(得分:0)

大多数(如果不是所有)自动增量方案的工作方式是DB记住为每个这样的字段分配的最后一个数字,并且插入的下一个记录总是得到+1。所以它只需记住1个数字:分配的最后一个数字。

假设您插入了5条记录。他们得到1,2,3,4,5。现在你删除2和4.数据库如何知道在接下来的两个插入中重复使用2和4?

我想,它可以扫描表格中的所有记录,每次插入时都会查找序列中的第一个孔。但是每次插入都需要读取表中的每条记录。如果表有数百万条记录会怎样?插入可以从花费几分之一毫秒到花费几分钟。

它可以保留已删除记录的表格。据推测,每次进行插入时,它只会从表中拉出第一个数字。但是,现在每个插入都是:检查表格。有记录吗?如果是,请取该号码,删除记录。如果没有,请使用下一个可用号码。该表必须同步,以便如果多个用户正在添加记录,我们不会两次给出相同的数字。如果有很多删除,它可能会变得非常大。即使每次我们进行插入只是一次额外读取,我们现在做两次操作而不是一次:性能将减少一半。

好的,我们可以处理当前分配的最高数字被删除时的特殊情况,然后从我们的最高数量 - 远远分配的值中减去一个。可行,但是对于那个特例,是否值得制定特殊规则?您多久删除一次插入的记录?如果删除基本上是随机命中的,则该记录将被删除的可能性很小。

总是分配一个新号码有明显的好处:

一:简单。这种行为很简单,很容易预测。没有特殊情况。

二:速度。如上所述,替代方案需要额外的工作也许不是很多,但如果我们只需要为每个插页处理一个额外的记录,我们就会将性能降低一半。

三:我们可以使用指定的号码告诉我们添加记录的顺序。高数字记录总是比低数字记录更新。在进行即席查询和追踪问题时,我经常发现这很方便。

四:我们避免潜在的错误联系。假设你向表A添加一条记录,然后它被分配,例如,编号12.然后你向表B添加一条包含对表A的引用的记录,所以我们插入那个数字12.让我们假设对于任何一种您没有将其声明为外键的原因。然后你从表A中删除记录12.所以现在你在表B中有这个悬空引用。那很糟糕。但是想象一下新的记录被添加到A并且它得到一个回收的数字12.现在我们在B中有一个记录指向A中的错误记录。悬空指针很糟糕,但错误的指针更糟。客户因其他人的指控而被收费,或者因犯罪而被逮捕的人员

更复杂系统的收益会是什么?我看到的唯一好处就是我们不太可能会耗尽可能的数字。但如果序列号是一个4字节的整数,则有20亿个可能的值。有多少表在其生命周期内获得20亿个插入?当然,如果该表有50亿条记录,无论您是否尝试重复使用数字,都会遇到问题。我想如果你有一个非常高容量的队列,不断添加新记录而旧记录丢失,这可能是一个问题。或者,如果您不断删除记录并重新插入记录而不是进行更新。但坦率地说,我已经从事这项业务已有30年了,而且我从来没有遇到任何问题,因为数据库中的自动序列没有数字。我不怀疑它发生在某个地方,但这不是一个常见的问题。我认为它不足以让一个干净,简单的系统崩溃。

答案 3 :(得分:0)

您不希望重复使用数字。它没有任何优势。他们毫无意义。不要依赖具有任何给定值的任何ID的值。