数据库模型设计——主键的设计

数据库模型设计——主键的设计

2023年7月13日发(作者:)

数据库模型设计——主键的设计在数据库设计时,主要就是对实体和关系的设计,实体表现出来就是表,关系表现出来就是外键。⽽对于⼀个表,由两部分组成:主键和属性。主键的简单定义就是表中为每⼀⾏数据的唯⼀标识。其实更准确的说法,每⼀⾏数据的唯⼀标识是候选键(Candidate Key),⼀个表中可以有很多个候选键,主键是候选键中的⼀个,主要⽤于更⽅便的检索和管理数据。⼀个表中可以有多个候选键,但是只有⼀个主键。由于主键常常⽤于检索数据,也⽤于表之间的关联,所以主键的设计的好坏将会严重影响数据操作的性能。下⾯来介绍下主键设计的⼏个考虑因素。主键的数据类型最常见的主键数据类型是数字类型、固定长度的字符类型和GUID类型。通常情况下,RDBMS会在主键上建⽴聚集索引(SQL Server默认都这么做),由于我们使⽤B-Tree的数据结构来存储索引数据,所以⼀般对主键有以下两个要求:越短越好——越短在⼀个Page中存储的节点越多,检索速度就越快。顺序增长——如果每⼀条插⼊的数据的主键都⽐前⾯的主键⼤,那么B-Tree上的节点也是顺序增长的,不会造成频繁的B-Tree分割。越短越好是为了查询的速度快,顺序增长是为了插⼊速度快。有了这两个要求,我们再来分析下各个数据类型:数字类型:根据数据量决定是⽤Int16还是Int32或者Int64,能⽤Int32的就不需要使⽤Int64。字符类型:基本不满⾜前⾯提到的2点要求,字符类型⼀般不会很短,⽽且也很可能不是顺序增长的,所以不是特别推荐的主键类型。当然如果确实业务需求使⽤字符类型,那么也尽量使⽤char(XX)⽽不要使⽤varchar(XX),因为在RDBMS中,对于定长字符串和变成字符串的数据结构和处理是不⼀样的,varchar的性能更差。GUID类型:这个类型并不是所有数据库都有对应的数据类型,SQL Server有uniqueidentifier,MySQL没有。GUID类型在SQL Server中是16个字节,不算短,⽐4个字节的Int32长多了。在插⼊新数据时,GUID⼀般都是使⽤NewId()这样的⽣成随机GUID的⽅式⽣成的,所以也不是顺序增长的,在插⼊速度上不会很快。通过上⾯的⽐较,我们知道使⽤数字类型是更好的⽅式,那么我们为什么还会有⼈使⽤GUID和字符串来当主键呢?那是因为:相对于数字类型,字符类型更易读易记,在检索关联的数据时,更⽅便直接。GUID的优势是全球唯⼀,也就是说同样的系统,如果部署了多套环境,那么⾥⾯的数据的主键仍然是唯⼀的,这样有助于数据的集成。典型的例⼦就是⼀个系统在全国每个省份都部署⼀套,每个省份的数据各种录⼊,互不⼲扰,然后再把每个省的数据集成起来为总部做分析。数据库主键与业务主键前⾯说到⼀个表可能有很多个唯⼀标识的候选键,那么这么多候选键中,哪个应该拿来做主键呢?⼀种⽅案是再新建⼀个独⽴的字段作为主键,该字段并没有业务含义,只是⼀个⾃增列或者流⽔号,⽤于唯⼀标识每⼀⾏数据,这是数据库主键。另外⼀种⽅案是选择其中较短较常⽤的属性作为主键,这是业务主键。个⼈建议是不要使⽤任何有业务含义的字段作主键,⽽是使⽤⼀个⾃增的(或者系统⽣成的)没有实际业务意义的字段作为主键。为什么呢?主要是出于以下考虑:具有业务意义的字段很可能是⽤户从系统录⼊的,不要信任⽤户的任何输⼊,只要是⽤户⾃⼰录⼊的,那么就很有可能录错了,如果发现录⼊错误,这个时候再对主键进⾏修改,将会涉及到⼤量关联的外键表的修改,是很⿇烦的⼀件事情。⽐如在做⼈员表的时候,就不要使⽤员⼯号或者⾝份证号做主键。具有业务意义的字段虽然在当前阶段是唯⼀的,是不变的,但是并不能保证随着公司政策变动、业务调整等原因,导致该业务字段需要修改,以满⾜新的业务要求,这个时候要修改主键也是很⿇烦的事情。⽐如部门表,我们以部门Code作为主键,但是后来部门变动,Code修改,则系统部门表的主键也得更改。还有⼀个原因是业务主键在数据录⼊的时候不⼀定是明确知道的,有时我们会在不知道业务主键的情况下,就录⼊其他相关信息,这个时候,如果使⽤业务主键做数据库的主键,那么数据将⽆法录⼊。⽐如员⼯表把员⼯号作为主键,那么员⼯还没有⼊职,没有员⼯号的时候,HR需要先维护⼀些该预⼊职员⼯的信息是不可能的。联合主键联合主键就是以多个字段来唯⼀标识每⼀⾏数据。前⾯已经说到主键应该越短越好,⽽且是建议是⼀个没有意义的⾃增列,那么是不是就不会再需要联合主键呢?答案是否定的,我们仍然可能会使⽤到联合主键。联合主键主要使⽤在多对多的关系时,中间表就需要使⽤联合主键。在简单的多对多关系中,我们不需要为中间的关联建⽴实体,所以中间表可能就只需要两列,分别是两个实体表的主键。主键值的⽣成主键值的⽣成可以参考NHibernate的配置,概况下来主要有这么⼏种⽣成⽅式:⾃增,这是SQL Server常⽤的主键⽣成⽅式,完全由数据库管理主键的值。Sequence对象,这是Oracle常⽤的主键⽣成⽅式,现在SQL Server已⽀持。主要是在数据库中有⼀个Sequence对象,通过该对象⽣成主键。GUID,这是⽤于GUID类型的主键,可以使⽤newid()这种数据库提供的函数,或者使⽤程序⽣成Guid并赋值。Hilo值,这是⼀种使⽤⾼低位算法⽣成的数字值的主键。该值由NHibernate程序内部⽣成。其他程序赋值,完全由程序根据⾃⼰的算法⽣成并赋值。更详细的主键⽣成,我们可以参见:主键与索引在概念和作⽤上,主键与索引是完全两个不同的东西,但是由于我们⼤部分情况下都是使⽤主键检索数据,所以⼤部分数据库的默认实现,在建⽴主键时会⾃动建⽴对应的索引。以SQL Server为例,默认情况下,建⽴主键的列,就会建⽴聚集索引,但是实际上,我们可以在建⽴主键时不使⽤聚集索引。另外还有⼀个唯⼀约束(索引)的概念,该索引中的数据必须是唯⼀不能重复的,感觉和主键的意义⼀样,但是还是有⼀点点区别。主键是只能由⼀个,⽽唯⼀约束(索引)在⼀个表中可以有多个。主键不能为空,⽽唯⼀约束(索引)是可以为空的。

发布者:admin,转转请注明出处:http://www.yc00.com/web/1689246348a225613.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信