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