我有一个具有非自动递增主键的现有模式。该键在其他十几个表中用作外键。
我继承了一个有重大性能问题的程序。目前,当向该表添加新行时,创建新的唯一id的方式如下:
1) a query for all existing primary key values is retrieved
2) a random number is generated
3) if the number does not exist in the retrieved values, use it, otherwise goto (2)
该应用程序是多线程和多服务器的,所以简单地在启动时获取一次现有的ids不是一个选择。我没有从发起请求中获取并转换为伪唯一值(如成员id)的唯一信息。
我知道在理论上可以在内部执行操作,以将自动递增添加到现有的主键。我知道系统地删除指向这个表的所有外键也是可能的,然后创建-重命名-插入一个新版本的表,然后添加回来的外键,但是这个表格式是由第三方应用程序决定的,如果我搞砸了,那么糟糕的事情就会发生。
有没有一种方法可以利用sql/mysql获得唯一的行值?
我想出的最接近的方法是从一个很大的空间中随机选择一个数字,并希望它在数据库中是唯一的,然后在发生奇怪的冲突时重试。
想法?
发布于 2014-09-18 01:12:12
如果表的主键未用于外键引用,则删除该主键。其目标是使您的列成为自动递增的主键。
因此,查找最大值,然后执行以下操作:
alter table t modify id int not null auto_increment primary key;
alter table t auto_increment = <maximum value> + 1;
我不认为有必要显式地设置auto_increment值,但我喜欢确定。
发布于 2014-09-18 01:16:47
我认为你可以选择MAX(‘strange id-column’)+1,这个值是唯一的,你可以把sql代码和插入代码放在一个事务中,以防止出错。
发布于 2014-09-18 01:33:09
拉回所有主键值的列表(对于大型集合),然后生成伪随机值并通过检查列表来验证它的唯一性,这似乎真的很昂贵。
我看到这种方法的一个大问题是,当序列以相同的种子值启动时,伪随机数生成器将生成相同的值序列。
如果发生了这种情况,那么将会有一次又一次的冲突,直到序列达到一个尚未使用的值。下一次发生这种情况时,你会再次遍历整个列表,以添加另一个值。
我不明白为什么这个值必须是随机的。
如果不需要伪随机性,并且升序值也可以,那么如果我不想对现有表进行任何更改,我会这样做:
我将创建另一个具有auto_increment列的“id生成器”表。我对该表执行插入操作以生成id值。
我不会运行查询从现有表中拉回所有现有的生成器值,而是执行一个插入到“id- id
”表中,然后执行一个SELECT LAST_INSERT_ID()
来检索我刚插入的行的id
,它将使用该值作为“生成的”id
值。
基本上,模拟Oracle SEQUENCE对象。没有必要将所有行都保存在"id-generator“表中。因此,我可以删除所有id
值小于最大id
值的行。
如果需要伪随机性(抖动),我可能只会尝试插入,以此来确定键是否存在。如果由于键重复而导致插入失败,我将使用不同的id
值重试。
伪随机生成器的重复序列吓到我了。如果我连续发生几次碰撞。这些是来自以前使用的序列,还是来自不同序列的值。我没有任何办法知道。放弃序列并重新开始一个新的种子,如果该种子以前已经被使用过,我将继续追逐之前生成的另一系列值。
https://stackoverflow.com/questions/25902626
复制