bitscn.com
我唯一还算熟悉的数据库就算是mysql了,大概使用mysql的人,百分之九九以上的人会使用autoincrement id做主键,这是可以理解的,因为mysql的自增id效率很高,使用也很方便。那么剩下的百分之一的人使用什么做主键呢?可能是自己做的keygenerator,也可能是我们下面要说的uuid。
据说在oracle的圈子里,如果谁用自增id做主键是要被鄙视的,主键最自然的选择就是uuid。我不了解oracle,这些道听途说的结论是否正确不做承诺。
那么我们先看看什么是uuid?简单的说,uuid是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。在uuid的算法中,可能会用到诸如网卡mac地址,ip,主机名,进程id等信息以保证其独立性。
如果你的mysql版本不太老的话,键入 select uuid(); 输出的就是uuid,如下:
mysql> select uuid();
+--------------------------------------+
| uuid() |
+--------------------------------------+
| 54b4c01f-dce0-102a-a4e0-462c07a00c5e |
+--------------------------------------+
现在大家应该对uuid有一个比较直观的认识了,我们来看看uuid的优缺点分别是什么。
优点:
能够保证独立性,程序可以在不同的数据库间迁移,效果不受影响。
保证生成的id不仅是表独立的,而且是库独立的,这点在你想切分数据库的时候尤为重要。
缺点:
比较占地方,和int类型相比,存储一个uuid要花费更多的空间。
使用uuid后,url显得冗长,不够友好。
下面针对上述uuid的缺点说说我的看法,比较占地方这个缺点我不是很在乎,现在最不值钱的就是硬盘了,略过此条缺点无妨,但需要注意的一点数据在索引的时候效率会随着体积的增加而降低。至于说使用uuid后,url显得不友好,我觉得这多少是你的int情结造成的惯性思维,其实,和int类型相比,uuid才是最自然的主键选择,注意,我这里用的是自然这个形容词,仔细体会一下你能理解我的意思。另外,很多时候,url本身就不需要友好,比如,一个电子商务网站,按照int友好的url说法,她的订单url大概是下面这个形式的:/order.php/id/123,我要说明的是,这样是很友好,但是有些太友好了,友好的甚至不安全,比如说,我早晨下一个订单,发现url是/order.php/id/1000,晚上再下一个订单发现url是/order.php/id/2000,那么我就可以估计出此网站一天的订单数大致是1000左右,甚至能大体估计出它的销售额,而这些数据往往都是重要的商业秘密。使用uuid就没有这个顾虑。
效率?
如果上面说的uuid的所谓缺点都不成立的话,那么是否使用uuid做主键,唯一的问题就是效率了。据说在postgresql等数据库里,都有专门的uuid类型,在这样的数据库里,使用uuid做主键,效率没有任何问题,可惜在mysql里没有这样的字段,如果想在mysql里保存uuid做主键,一般是使用char(36)来模拟,因为不是一个原生的uuid类型,所以主键的效率到底如何有待测试,另外,uuid做主键的效率和uuid本身的算法实现也有很大关系。
另外,对于innodb这种聚集主键类型的引擎来说,数据会按照主键进行排序,由于uuid的无序性,innodb会产生巨大的io压力,此时不适合使用uuid做物理主键,可以把它作为逻辑主键,物理主键依然使用自增id。
我本来想在我自己的电脑上插入1000000条数据测试一下看看来着,可惜一测试,硬盘灯就一直亮,让我很担心它会挂,虽然硬盘不值钱,但是我重要的数据都在上面,一旦坏了,损失就大了,所以,测试只好作罢。
至于在mysql上使用uuid(用char(36)存储,也可以用binary(16)存储)做主键,效率到底如何,我也不知道,抱歉 -_-!!!
参考链接 (一)(二)(三)(四)(五)
弱水注:文章转载于http://hi.baidu.com/thinkinginlamp/blog/item/c609d10979710e81d0581b60.html
bitscn.com