自增主键的弊端

有人反对用自增的主键, 谁能指点下它的弊端,感激涕零!

作者: qcrsoft   发布时间: 2008-05-26

我个人觉得缺少弹性

当你有 1-10个ID 你删除了9个 只剩下1 再添加一次就是 11 而不是2

或者你有1-10个ID 你删除了8个 只剩下1和10 当你的最大ID仅仅到10的时候,你可以用一些算法来调整插入空缺ID

自增主键都是做不到的

时间越长ID变多,这些隐藏的问题暴露出来后,将变得越难以控制

作者: kzc_ljl   发布时间: 2008-05-26

:)

作者: kbryant   发布时间: 2008-05-26

楼上的楼上:
按我的猜想,让ID连续是为了类似翻页的便利是吗?如果是,这等于是无序的排列,在实际应用中几乎找不到没有一定序列的列表。或者我没理解你的意思

作者: qcrsoft   发布时间: 2008-05-26

引用 1 楼 kzc_ljl 的回复:
我个人觉得缺少弹性

当你有 1-10个ID 你删除了9个 只剩下1 再添加一次就是 11 而不是2

或者你有1-10个ID 你删除了8个 只剩下1和10 当你的最大ID仅仅到10的时候,你可以用一些算法来调整插入空缺ID

自增主键都是做不到的

时间越长ID变多,这些隐藏的问题暴露出来后,将变得越难以控制


怕的是以后大到超出你的想象的时候就出问题了

作者: Tll_W   发布时间: 2008-05-26

个人感觉,用自增ID是为了方便设主键,以满足第二范式的要求.插入记录也方便. 而且int型做为索引速度也快. id跟翻页没有关系.
如果你表有一个int型可做主键,没完没有必要用自增ID.

作者: xiaoqhuang   发布时间: 2008-05-26

int32最大可达20多亿, 就算经常删增也很少会达到最大的. 如果设计初能预见记录多太多,可用bigint. 2的63次方. 足够了.
我觉得用自增还是很不错的. 当然也有人建议用newId(), 仁人见仁.

作者: xiaoqhuang   发布时间: 2008-05-26

引用 1 楼 kzc_ljl 的回复:
我个人觉得缺少弹性

当你有 1-10个ID 你删除了9个 只剩下1 再添加一次就是 11 而不是2

或者你有1-10个ID 你删除了8个 只剩下1和10 当你的最大ID仅仅到10的时候,你可以用一些算法来调整插入空缺ID

自增主键都是做不到的

时间越长ID变多,这些隐藏的问题暴露出来后,将变得越难以控制

这个不是主键的问题而是你设计的问题...主键应该是无意义的与业务无关...也就是说主键不必是顺序的甚至不必是有规律的...

自增主键的弊端主要是主外键关系表的并发性能问题和分布式系统的唯一性问题...另外就是数字类型的溢出问题...

大型系统或分布式系统一般采用GUID作为主键...

作者: vrhero   发布时间: 2008-05-26

弊端啊,没有连续性,比如说你添加三条记录,编号就是1,2,3
然后你删除记录2,这样就变成了1,3了
如果你删除记录3,然后添加记录,就会变成1,2,4,5
明白了吗

作者: virusplayer   发布时间: 2008-05-26

弊端啊,没有连续性,比如说你添加三条记录,编号就是1,2,3 
然后你删除记录2,这样就变成了1,3了 
如果你删除记录3,然后添加记录,就会变成1,2,4,5 
明白了吗
=================================
最后会变成1,2,4,5,这个我明白,但有什么问题呢?

作者: qcrsoft   发布时间: 2008-05-26

自增主键的弊端主要是主外键关系表的并发性能问题和分布式系统的唯一性问题
==================
非常希望virusplayer 能给稍微详细解析下这句话包含的内容,洗耳恭听!

作者: qcrsoft   发布时间: 2008-05-26

本公司的数据库表用的是自增主键,用的是SQL SERVER,短期是没什么问题(3-4年了最多的表记录有20多万条).
不过就在出报表的时候表连接很多,速度慢.
大型数据库ORACLE一般不会用自增的主键.

作者: kaihuababy   发布时间: 2008-05-26

浪费我的聚集索引了哦 哦

作者: zhnzzy   发布时间: 2008-05-26

引用 1 楼 kzc_ljl 的回复:
我个人觉得缺少弹性

当你有 1-10个ID 你删除了9个 只剩下1 再添加一次就是 11 而不是2

或者你有1-10个ID 你删除了8个 只剩下1和10 当你的最大ID仅仅到10的时候,你可以用一些算法来调整插入空缺ID

自增主键都是做不到的

时间越长ID变多,这些隐藏的问题暴露出来后,将变得越难以控制


这根本就不是弊端,而是你的需求不同罢了.
有的人就正好有这样的需求,即使删除后,再插入一条一模一样的记录,也能因为这个值的不同而区分开.那这不成了利端?
Int型可以达到二十多亿,一张表里短期是很少会达到这个数量级的.

作者: zjmotion   发布时间: 2008-05-26

其实说白了,没有绝对的利弊,根据实际需求来做分析就对了.该自增就自增,不该自增就别自增.没有一定的说法.

作者: zjmotion   发布时间: 2008-05-26

不过就在出报表的时候表连接很多,速度慢. 
大型数据库ORACLE一般不会用自增的主键.
=====================================
据我的了解,相信出报表慢和是否自增没有关系,而且你也说了,是“表连接很多”,表连接的多和自增更没关系了
ORACLE里印象里也没有自增的主键,而是用nextval来产生一个键值

作者: qcrsoft   发布时间: 2008-05-26

有的人就正好有这样的需求,即使删除后,再插入一条一模一样的记录
===========================
你举的是比较极端特殊的例子,但现实中很多人都不用自增并非出于这样的考虑,我想知道的就是处于什么考虑而不用自增

作者: qcrsoft   发布时间: 2008-05-26

没感觉有弊端,像RoR还强制要求每一个表必须有一个自增id呢

作者: fuadam   发布时间: 2008-05-26

个人觉的自增id存在不连续性,如当你有 1-10个ID 你删除了9 只剩下1 再添加一次就是 11 而不是2 
  那么显示出来数据如下: 1 ...
  11 ...
 这样不如这样的数据条理化: 1 ......
  2......

作者: wuzy1229   发布时间: 2008-05-26

学习了!!
感谢大家!!

作者: yagebu1983   发布时间: 2008-05-26

没有弊端,自增int型主键用作排序,检索起来也很块!不要被别人误导了,根据项目需求来!

作者: ludeli2004   发布时间: 2008-05-26

个人觉的自增id存在不连续性,如当你有 1-10个ID 你删除了9 只剩下1 再添加一次就是 11 而不是2  
  那么显示出来数据如下: 1 ... 
  11 ... 
 这样不如这样的数据条理化: 1 ...... 
  2......
========================================
从你的视角回复你:
从五月一日到10日每天写一条记录,序号分别内是1-10
11号这天删除2号的,再写入一条记录,它的ID=2
于是你在界面上看到的数据是:
标题一 2008.05.01
标题xx 2008.05.11
标题三 2008.05.03
不知这是否是你要的效果

另外为了保持“见缝插针”,我想你每insert一次就得把数据全部读出然后从前往后循环寻找第一个空缺,是不是?

作者: qcrsoft   发布时间: 2008-05-26

数据迁移时,问题非常大。

作者: tnt1980   发布时间: 2008-05-26

没有弊端,自增int型主键用作排序,检索起来也很块!不要被别人误导了,根据项目需求来!
===============================================================
TO : ludeli2004 
我所想知道的,正是在什么需求下需要"非自增"

作者: qcrsoft   发布时间: 2008-05-26

数据迁移时,问题非常大
======================
tnt1980兄弟给举个例子吧,我以前面试时,考官提出的反对意见印象里不是迁移句是备份,可惜当时没求教,你给说说吧

作者: qcrsoft   发布时间: 2008-05-26

引用 8 楼 virusplayer 的回复:
弊端啊,没有连续性,比如说你添加三条记录,编号就是1,2,3
然后你删除记录2,这样就变成了1,3了
如果你删除记录3,然后添加记录,就会变成1,2,4,5
明白了吗

作者: netfeel2008   发布时间: 2008-05-26

自己定义的就有连续性么???
呵呵!
自生成ID最大的好处就是自我管理

作者: gxj760998   发布时间: 2008-05-26

引用 16 楼 qcrsoft 的回复:
有的人就正好有这样的需求,即使删除后,再插入一条一模一样的记录
===========================
你举的是比较极端特殊的例子,但现实中很多人都不用自增并非出于这样的考虑,我想知道的就是处于什么考虑而不用自增

这样的例子是很平常的,保持记录的绝对唯一性.而且这个是需要自增的,并不是你说不需要自增.
现在很明显了,没有什么利弊,根据你的需求来.比如,存储全国各省市县的数据表,省市县本身就是唯一的,类似的还有IP表.
我觉得这个真的没有什么可讨论性.

各位继续吧.

作者: zjmotion   发布时间: 2008-05-26

引用 26 楼 gxj760998 的回复:
自己定义的就有连续性么???
呵呵!
自生成ID最大的好处就是自我管理


这个结论太泛泛,想象不出“自我管理”的好处和需求,举个例子说明下吧

作者: qcrsoft   发布时间: 2008-05-26

引用 27 楼 zjmotion 的回复:
引用 16 楼 qcrsoft 的回复:
有的人就正好有这样的需求,即使删除后,再插入一条一模一样的记录
===========================
你举的是比较极端特殊的例子,但现实中很多人都不用自增并非出于这样的考虑,我想知道的就是处于什么考虑而不用自增

这样的例子是很平常的,保持记录的绝对唯一性.而且这个是需要自增的,并不是你说不需要自增.
现在很明显了,没有什么利弊,根据你的需求来.比如,存储全国各省市县的数据表,省市…


这个例子没有说服里
假设有个城市表1000条记录,删除第100条的“上海”,然后又增加了“泉州”,把泉州经过计算写成100比自动写为1001必要在什么地方呢?
至于IP表,一样想象不出有什么样的需求要要保持ID连续

“根据你的需求来”——我真是想不出在什么时候才会出现这样的需求,所以才问的

作者: qcrsoft   发布时间: 2008-05-26

关注,本人也想不出有什么弊端

作者: huangdanming   发布时间: 2008-05-26

排序的时候貌似会乱
如1~10的记录
读出来就是:1,10,2,3,4...,9 了。。。(GridView)

作者: fly4free   发布时间: 2008-05-26

引用 31 楼 fly4free 的回复:
排序的时候貌似会乱
如1~10的记录
读出来就是:1,10,2,3,4...,9 了。。。(GridView)


没看出是站哪边的兄弟

作者: qcrsoft   发布时间: 2008-05-26

引用 22 楼 tnt1980 的回复:
数据迁移时,问题非常大。


极力赞成,确实问题非常大

作者: superhjtc   发布时间: 2008-05-26

某些时候所谓的弊端在另外一些时候就是优势,例子不举了。
硬要举出弊端,可能随便一个技术都会有人找出其不足。

你如果不是评论家,不要在意这个。
只要在设计的时候考虑到极端的情况(边界情况?术语可能不对,但跟测试时候有关),根据这些情况是否会对系统产生什么样的影响,以此来决定是否用它即可。

作者: fly4free   发布时间: 2008-05-26

引用 34 楼 fly4free 的回复:
某些时候所谓的弊端在另外一些时候就是优势,例子不举了。
硬要举出弊端,可能随便一个技术都会有人找出其不足。

你如果不是评论家,不要在意这个。
只要在设计的时候考虑到极端的情况(边界情况?术语可能不对,但跟测试时候有关),根据这些情况是否会对系统产生什么样的影响,以此来决定是否用它即可。


这里有个含糊的概念:
需求上要考虑“极端的情况”的情况,但咱们的讨论在系统设计的范畴,设计无从谈起“极端的情况”,设计满足需求就是好设计。举个你可能认可的例子:数据库中的字段是byte型,你的系统对应的某个变量一定要搞成long型,因为这样可以最大程度的满足某种想象不出的”极端的情况“,不太合适吧?

大家是在讨论具体的问题,“某些时候”、“随便一个”的泛泛而谈对大家都是浪费时间

作者: qcrsoft   发布时间: 2008-05-26

如果不是大型系统或分布式系统...自增主键没有什么弊端...如果有...说明你的设计有问题...

数据迁移时也不会有什么问题...如果有...说明你的迁移计划有问题...

作者: vrhero   发布时间: 2008-05-26

系统设计的范畴?
按你的思路,那也无从谈起“弊端”。因为“弊端”是在系统最后运行起来后才发现的
(至于设计之前就知道,那是因为有了前人在多次“系统最后运行”多次后的经验总结)

设计是为了运行,所以设计阶段是要“根据经验来考虑各种极端情况”,如:溢出怎么办?我想显示ID,用N位宽高位不足用0补,怎么办?……
设计脱离不了需求。

这类问题在楼上们的回答中有些都给出具体不足的情况了,还要怎么具体?
A问:筷子有几种用途?B:答,吃饭,剔牙,起啤酒瓶盖,沾水写字画画…… ,你要这样的具体?


PS:你举的例子我没理解。1.我不会搞成long型。2.看不懂后面“因为”相关描述,这和搞成long型根本不搭边。

作者: fly4free   发布时间: 2008-05-26

如楼上说的属系统设计范畴?关于他,楼上的兄弟们都说的很多了,不过大都是从实现和技术上说的,我想从设计的一个角度上说下。
如果使用通常的方法设主建或联合主建,那他就有不仅仅用来标识唯一记录,他还包含了业务逻辑在里面;而采用自增主建,自增字段就是只用来标识唯一记录的,而不附加别的含义。
如:我们设计一个订单表,如果用普通方法设主建的化,那直接就可以用订单编号做主建就行,因为系统中就根本不会有编号重复的订单,但在这种设计下,这个订单编号除了当主建唯一标识记录用,他在你系统中是有真实含义的(即:订单的编号)。而采用自增主建,他在系统中没有任何真实含义,只是一个数字,用来标识记录用。
所以的话,选择那种,就看你系统的设计了。
不过个人认为如果系统比较大且业务逻辑复杂的话使用自增主建是一个好的选择,因为你每张表的主建不包含真是含义,也就和系统的业务逻辑是分开的,这样就减少主建的二意行,有助于系统业务逻辑层代码编写。

不知道这个例子具得是否恰当,要靠lz体会了,呵呵.

作者: liujunhappy2005   发布时间: 2008-05-26

又详细看了上面兄弟们的意见,对数据迁移讨论的比较激烈。关于这个问题,我也阐述下自己的看法,有兄弟说自增一主建不连续,不适合迁移,这是对自增一主建的偏见。
还拿上面的订单为例,从客观实际出发,数据迁移,侧重点在于把编号为002的订单数据及其子数据(订单明细表中相对应的数据),从一个数据库移到另一数据库,而不在乎编号为002的订单在2个数据库中的具体位置;如果将数据迁移做成,在原数据库第一或第二甚至第三位置的002号订单,移动到新数据库中相应的第一或第二甚至第三位置,那这不是数据迁移,叫数据库拷贝,机械的复制,是个太理想话方式,不符合实际情况,因为就算你原系统写的非常完美,绝对不出错,能保证的主建值(即订单编号)和在原数据库的位置相同,你也保证不了操作人误操作、计算机硬件系统出错等不可预知的错误,而导致主建值和在数据库中位置不一致,就别提世界上就没有100%完美的软件系统,所以将注意力集中在记录在数据库中的位置,这是一个非常不好的数据迁移方案.

作者: liujunhappy2005   发布时间: 2008-05-26

引用 37 楼 fly4free 的回复:
系统设计的范畴?
按你的思路,那也无从谈起“弊端”。因为“弊端”是在系统最后运行起来后才发现的
(至于设计之前就知道,那是因为有了前人在多次“系统最后运行”多次后的经验总结)

设计是为了运行,所以设计阶段是要“根据经验来考虑各种极端情况”,如:溢出怎么办?我想显示ID,用N位宽高位不足用0补,怎么办?……
设计脱离不了需求。

这类问题在楼上们的回答中有些都给出具体不足的情况了,还要怎么具体?…


抛开你的上贴和我的上贴互相不理解的部分不谈了,举个例子总可以吧

作者: qcrsoft   发布时间: 2008-05-27

未见弊端

作者: superdullwolf   发布时间: 2008-05-27

挺好不错,各有千秋.

作者: ilyljj   发布时间: 2008-05-27

自增主键最大的弊端是你不知道插入的是那条记录,比较难以得到关键字

作者: jdlsfl   发布时间: 2008-05-27

感觉要看用在什么地方,根据需要而来.比如象一些商业应用中的记录消费流水等这种表里应用非常好。

作者: red_fish   发布时间: 2008-05-27

主键一个很重要的作用是标志唯一,用了ID自增长,你就不用在程序中考虑这样的问题!反之,你需要用代码来管理。
这个是一个好处,至于坏处也有,看你怎么平衡啦!

作者: gxj760998   发布时间: 2008-05-27

自增主键...缺点
1.在插入数据时无法确定主键的值,除非使用事务否则,通过其它方法获得,无法保证获得的值就是刚插入数据的主键,因为在插入数据库前无法获得主键导致后续代码编写困难.
2.自增值在使用事务回滚,以及在插入失败的情况下,其值不会回滚,当使用此值作为条目的连续编号时回发生编号不连续的问题.
3.在合并数据库表时,因为都是从1开始编号造成数据合并困难,特别对于一些可以离线的操作的系统,自动编号只是累赘..

因以上几点我的数据库的主键已全部改为GUID.

作者: zhiang75   发布时间: 2008-05-27

缺点:
数据集成,
数据导入,
大系统分布系统并发;

问题的核心在于:作为业务逻辑的主键和记录并发\唯一性放在一个字段了,应该解耦.

作者: cacar2008   发布时间: 2008-05-27

引用 47 楼 cacar2008 的回复:
缺点:
数据集成,
数据导入,
大系统分布系统并发;

问题的核心在于:作为业务逻辑的主键和记录并发\唯一性放在一个字段了,应该解耦.


支持一个..问题的关键阿..

作者: zhiang75   发布时间: 2008-05-27

省份证号的问题
13亿
删除添加删除添加

作者: liyangfd   发布时间: 2008-05-28

作者: chappell1   发布时间: 2009-03-11

ding

作者: metaphy   发布时间: 2009-03-11

数据迁移时,问题非常大。
这问题能解决



把自增消除掉然后
一条UPDATE语句
一条INSERT INTO SELECT就OK

ClassTableA  
ClassID ClassName
1 初一1班
2 初一2班
3 初一3班

ClassTableB  
ClassID ClassName
1 初一4班
2 初一5班
3 初一6班
----------------------
UPDATE后

ClassTableB  
ClassID ClassName
4 初一4班
5 初一5班
6 初一6班
----------------------
INSERT INTO SELECT后
ClassTable
ClassID ClassName
1 初一1班
2 初一2班
3 初一3班
4 初一4班
5 初一5班
6 初一6班

作者: cw333777   发布时间: 2009-03-11

学习了、、、

作者: Lester_2008   发布时间: 2011-05-13