闲谈系列之一——数据库主键GUID
昨日一个行内兄弟由于工作调动要派到某二线城市工作,虽然有高额工资和补助的诱惑但也难以释怀离京蛋蛋的忧桑,约好晚上到老聚点道个别、主要是聊(chui)聊(chui)前(niu)程(bi),几瓶夺命大绿棒子下肚,这货问起我现在项目的情况(操蛋的技术控!),我简单的说了一下架子和数据库,果然在数据库主键上出现了分歧,在他心里主键就是应该是妥妥的自增整型,对于我的GUID无法容忍,并指出GUID不连续、效率低下、blablabla,最后我说了一下我的解决方案总算得到了一定程度的肯定吧。。。
对于程序猿来说,数据库设计是永恒的话题,而主键作为数据库的重要元素是却并未得到应有的重视。本文仅对自增整型和GUID做简单对比,其他复合式、时间序列式等形式的主键暂不考虑。
主键的定义(From 百度知道)
主键:表中经常有一个列或列的组合,其值能唯一地标识表中的每一行。这样的一列或多列称为表的主键,通过它可强制表的实体完整性。当创建或更改表时可通过定义 PRIMARY KEY 约束来创建主键。一个表只能有一个 PRIMARY KEY 约束,而且 PRIMARY KEY 约束中的列不能接受空值。由于 PRIMARY KEY 约束确保唯一数据,所以经常用来定义标识列。
对自增量主键和GUID主键进行优劣对比(欢迎补充)
自增量主键
优势:
数据库自动生成,无需在业务中做任何管理
节省内存空间
数据写入和检索时效率较高
劣势:
数据合并、迁移时易出现问题,这一点的重要性因具体项目而定。
GUID主键
优势:
能在业务层就知道目标ID,而不是数据提交给数据库系统后才确定。
在分表时好处明显。
在数据库合并、迁移等方面十分方便。
劣势:
占用存储空间稍大(对于当前硬件及RDBS情况几乎可以忽略)
生成无序,检索数据时较自增整型主键效率严重下降(通过其他方式解决)
由于我的项目可能会经常性升级并且对数据持久性要求较高,果断选择GUID作为数据主键,当然随之而来的就是对检索效率的怀疑。
其实GUID主键检索效率低下的真正原因是聚合索引,当创建一个数据表时,系统会自动在主键上创建聚集索引,根据聚集索引的实现原理,无序的GUID无法发挥出聚集索引的作用,并且GUID做聚集索引可能还会引起叶分裂问题,严重杜绝把聚集索引建在GUID上!
也许你会考虑是否有有序的GUID?答案是肯定的!C#中内置了有序GUID的生成方法,但是只能在联网的情况下保证全球唯一,并且如果遇到服务器重启、系统重启等情况生成的GUID将无法与重启前的GUID保持正常顺序。
针对聚集索引这里我做了一些小的改动,首先我将GUID主键的主键约束移除,并设置不可空+唯一性约束,出于归档考虑我的每张表中都会有【数据产生时间】列,将原属于主键的聚集索引添加到该类上,保障了聚集索引的正常工作。
由于暂时项目进度太紧,没有做测试数据,理论上还算可行吧,以后有时间再补。。