【发布时间】:2011-01-07 13:16:57
【问题描述】:
我有 1 亿行,而且它变得太大了。 我看到很多差距。 (因为我删除,添加,删除,添加。)
我想用自动增量来填补这些空白。 如果我重置它..有什么危害吗?
如果我这样做,它会填补空白吗?:
mysql> ALTER TABLE tbl AUTO_INCREMENT = 1;
【问题讨论】:
标签: mysql database auto-increment
我有 1 亿行,而且它变得太大了。 我看到很多差距。 (因为我删除,添加,删除,添加。)
我想用自动增量来填补这些空白。 如果我重置它..有什么危害吗?
如果我这样做,它会填补空白吗?:
mysql> ALTER TABLE tbl AUTO_INCREMENT = 1;
【问题讨论】:
标签: mysql database auto-increment
可能非常危险,因为您可以再次获得一个已经在使用的号码。
您建议将序列再次重置为 1。它只会产生 1,2,3,4,5,6,7,.. 等等,无论这些数字是否存在差距。
更新: 根据 Martin 的回答,由于涉及的危险,MySQL 甚至不会让你这样做。它会将计数器重置为至少当前值 + 1。
再想想差距的存在会导致什么真正的问题。通常这只是一个审美问题。
如果数字太大,切换到更大的数据类型(bigint 应该足够了)。
【讨论】:
这样做您可能不会获得任何好处,而且您很容易通过覆盖行来搞砸您的应用程序,因为您要重置 ID 的计数。 (换句话说,下次插入一行时,它会覆盖 ID 为1 的行,然后是2 等。)填补这些空白会得到什么?如果数字太大,只需将其更改为larger number(如BIGINT)。
编辑:我的立场是正确的。它根本不会做任何事情,这支持了我的观点,即您应该将列的类型更改为更大的整数类型。 BIGINT 的最大可能值为 2^64,超过 18quintillion。如果您目前只有 1 亿行,那么在可预见的未来应该是很多。
【讨论】:
我同意 musicfreak... 整数 (int(10)) 的最大值为 4,294,967,295(无符号粗略)。如果您需要更高,切换到BIGINT 可以让您达到 18,446,744,073,709,551,615。
【讨论】:
FWIW...根据MySQL docs申请
ALTER TABLE tbl AUTO_INCREMENT = 1
tbl 包含现有数据的地方应该没有影响:
改变值 AUTO_INCREMENT 计数器用于 新行,这样做:
ALTER TABLE t2 AUTO_INCREMENT = 值;
您不能将计数器重置为 值小于或等于任何 已经被使用了。对于 MyISAM,如果 该值小于或等于 当前的最大值 AUTO_INCREMENT 列,值为 重置为当前最大值加一。 对于 InnoDB,如果值小于 中的当前最大值 列,不会发生错误,并且 当前序列值没有改变。
我为 MyISAM 表运行了一个小测试,证实了这一点。
因此,您的问题的答案是:没有害处,不,它不会填补空白。正如其他响应者所说:更改数据类型似乎是最不痛苦的选择。
【讨论】:
由于您无法更改下一个自动增量值,因此您还有其他选择。可以进行数据类型切换,但对我来说似乎有点不安,因为您实际上并没有那么多行。您必须确保您的代码可以处理这么大的 ID,这对您来说可能困难,也可能不困难。
你能做很多停机时间吗?如果是的话,我能想到两种选择:
转储/重新加载数据。您可以这样做,这样它就不会保留 ID 号。例如,您可以使用 SELECT ... INTO 将数据(无 ID)复制到具有相同 DDL 的新表中。然后删除旧表并将新表重命名为旧名称。根据有多少数据,这可能需要相当长的时间(和临时磁盘空间)。
您可以编写一个小程序来发出 UPDATE 语句来更改 ID。如果你让它慢慢运行,它会随着时间的推移对你的 ID 进行“碎片整理”。然后您可以暂时停止插入(只需一两分钟),更新最后的 ID,然后重新启动它。更新最后一个 ID 后,您可以将 AUTO_INCREMENT 值更改为下一个数字,您的洞就会消失。这应该不会导致任何真正的停机(至少在 InnoDB 上),但可能需要相当长的时间,具体取决于您的程序的激进程度。
当然,这两者都忽略了参照完整性。我假设这不是问题(不用作外键的日志语句等)。
【讨论】:
是否有差距真的很重要吗?
如果你真的想回去填充它们,你总是可以关闭自动增量,并在每次你想插入一行时手动扫描下一个可用的 id -- 记住锁定表以避免竞争条件,当然。但是做很多工作却收获不大。
您真的需要代理键吗?根据数据(您没有提到架构),您可能会找到一个自然键。
【讨论】: