Database design -- primary key design

Database design -- primary key design

 

 

       When designing a database, it is mainly the design of entities and relationships. The entities are represented as tables, and the relationships are represented as foreign keys. For a table, it consists of two parts: primary key and attributes. A simple definition of a primary key is a unique identifier for each row of data in a table. In fact, it is more accurate to say that the unique identifier of each row of data is the candidate key (Candidate Key). There can be many candidate keys in a table. The primary key is one of the candidate keys, which is mainly used for more convenient retrieval and management of data. A table can have multiple candidate keys, but only one primary key. Since the primary key is often used for retrieving data and for the association between tables, the quality of the primary key design will seriously affect the performance of data operations.

 

 

 

 

primary key data type

 

  • Number type
  • fixed-length character type
  • GUID type.

 

Generally, there are two requirements for the primary key:

 

  • Shorter is better: The shorter the number of nodes stored in a Page, the faster the retrieval speed.
  • Sequential growth: If the primary key of each inserted data is larger than the previous primary key, then the nodes on the B-Tree also grow sequentially, which will not cause frequent B-Tree splits.

 

  • The shorter the better, the faster the query
  • Sequential growth is for fast insertion

 

Primary key type analysis:

 

  • Number type: For MySQL, int is generally enough. You can use the database to auto-increment or the system to do the auto-increment yourself.
  • Character type: It basically does not meet the two requirements mentioned above. The character type is generally not very short, and it is likely not to grow sequentially, so it is not a particularly recommended primary key type. Of course, if the business needs to use character types, try to use char(XX) instead of varchar(XX), because in RDBMS, the data structure and processing of fixed-length strings and strings are different. varchar has worse performance.
  • GUID type: Not all databases have corresponding data types for this type, SQL Server has uniqueidentifier, MySQL does not. GUID type is 16 bytes in SQL Server, which is not short, much longer than 4 bytes Int32. When inserting new data, GUIDs are generally generated by using NewId() to generate random GUIDs, so they do not increase sequentially, and the insertion speed will not be very fast. Of course, the system can also do UUID.

 

问题:通过上面的比较,我们知道使用数字类型是更好的方式,那么我们为什么还会有人使用GUID和字符串来当主键呢?

 

  • 字符串或GUID是唯一的,适合分布式系统
  • 数据导入时不容易出现冲突
  • 降低插入速度,不影响查询速度

 

 

 

数据库主键与业务主键

 

哪些情况可以拿来做主键

 

  • 一种方案是再新建一个独立的字段作为主键,该字段并没有业务含义,只是一个自增列或者流水号,用于唯一标识每一行数据,这是数据库主键。
  • 另外一种方案是选择其中较短较常用的属性作为主键,这是业务主键。

 

建议

 

       不要使用任何有业务含义的字段作主键,而是使用一个自增的(或者系统生成的)没有实际业务意义的字段作为主键。

 

 

为什么?

 

  • 具有业务意义的字段很可能是用户从系统录入的,不要信任用户的任何输入,只要是用户自己录入的,那么就很有可能录错了,如果发现录入错误,这个时候再对主键进行修改,将会涉及到大量关联的外键表的修改,是很麻烦的一件事情。比如在做人员表的时候,就不要使用员工号或者身份证号做主键。
  • 具有业务意义的字段虽然在当前阶段是唯一的,是不变的,但是并不能保证随着公司政策变动、业务调整等原因,导致该业务字段需要修改,以满足新的业务要求,这个时候要修改主键也是很麻烦的事情。比如部门表,我们以部门Code作为主键,但是后来部门变动,Code修改,则系统部门表的主键也得更改。
  • 还有一个原因是业务主键在数据录入的时候不一定是明确知道的,有时我们会在不知道业务主键的情况下,就录入其他相关信息,这个时候,如果使用业务主键做数据库的主键,那么数据将无法录入。比如员工表把员工号作为主键,那么员工还没有入职,没有员工号的时候,HR需要先维护一些该预入职员工的信息是不可能的。

 

 

 

联合主键

 

       联合主键就是以多个字段来唯一标识每一行数据。前面已经说到主键应该越短越好,而且是建议是一个没有意义的自增列,那么是不是就不会再需要联合主键呢?答案是否定的,我们仍然可能会使用到联合主键。联合主键主要使用在多对多的关系时,中间表就需要使用联合主键。在简单的多对多关系中,我们不需要为中间的关联建立实体,所以中间表可能就只需要两列,分别是两个实体表的主键。

 

 

 

 

主键值的生成

 

 

自增

 

    数据库提供的自增长功能,新建一个ID字段,自动增长,非常方便也满足主键的原则。

 

    优点:

 

  • 速度快
  • 增量增长,聚集型主 键按顺序存放,对于检索非常有利
  • 数字型的,占用空间小,易排序,在程序中传递也方便

    缺点:

 

  • 数据导入时,怕出现ID冲突
  • 对于双主数据库,要重新设计增长,错开以免ID冲突

 

 

自制Max加一

 

    可以使用lock线程的方式,来避免同时拿到最大值;也可以将最大值放到redis,每次通过redis进行加一,因为redis时单线程而且适度非常快。

 

    优点:

 

  • 可以解决在分布式系统中生成主键ID的问题
  • 解决双主数据库ID冲突问题
  • 可以用数字型,可以用字符串类型

    缺点:

 

  • 数据导入时依然会怕ID冲突
  • 插入速度会比前面慢一点

 

 

GUID主键

 

    目前一个比较好的主键是采用GUID,当然我是推荐主键还是字符型的,但值由GUID生成,GUID是可以自动生成,也可以程序生成,而且键值不可能重 复,可以解决系统集成问题,几个系统的GUID值导到一起时,也不会发生重复,而且效率很高。

 

    优点:

 

  • 都是唯一的,导入数据不会出现冲突,便于数据迁移

    缺点:

 

  • GUID 值较长,不容易记忆和输入
  • 值是随机、无顺序的
  • 插入比前面慢点,查询应该差不多

 

 

Sequence对象

 

       这是Oracle常用的主键生成方式,现在SQL Server已支持。主要是在数据库中有一个Sequence对象,通过该对象生成主键。

 

 

 

Hilo值

 

       这是一种使用高低位算法生成的数字值的主键。该值由NHibernate程序内部生成。

 

 

 

 

主键与索引

 

       在概念和作用上,主键与索引是完全两个不同的东西,但是由于我们大部分情况下都是使用主键检索数据,所以大部分数据库的默认实现,在建立主键时会自动建立对应的索引。

 

       以MySQL为例,默认情况下,建立主键的列,就会建立聚集索引,但是实际上,我们可以在建立主键时不使用聚集索引。另外还有一个唯一约束(索引)的概念,该索引中的数据必须是唯一不能重复的,感觉和主键的意义一样,但是还是有一点点区别。

 

  • 主键是只能由一个,而唯一约束(索引)在一个表中可以有多个。
  • 主键不能为空,而唯一约束(索引)是可以为空的。

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326100579&siteId=291194637