【面试题集】数据库主键常用方式?为什么用自增列作为主键?

面试题集 专栏收录该内容
12 篇文章 2 订阅

品茗IT-面试题集-首发

如果大家正在寻找一个java的学习环境,或者在开发中遇到困难,可以加入我们的java学习圈,点击即可加入,共同学习,节约学习时间,减少很多在学习中遇到的难题。

常用主键生成方式

  1. Mysql自增长主键策略
    这种简单,不需要程序特别处理 ,但是这种方法对项目移植到其它数据库上改动会比较大,oracle、db2采用Sequence,Mysql、sqlServer又采用自增长,通用性不好 。
  2. 使用时间戳相关生成策略
    这种实现简单,与数据库无关,移植性较好 ,但长度太长,最少也得20位;
    比如雪花算法,可以生成20位有序的的ID。
  3. UUID、GUID
    这种方式简单,代码方便,全球唯一,与数据库无关,移植性较好,但没有排序,无法保证趋势递增。UUID往往是使用字符串存储,查询的效率比较低。
  4. 每次取主键最大值+1做为新的主键
    这种主键长度可控,移植性较好 ,但并发写可能会造成主键冲突,对并发也不太好控制
  5. 单独建一个存放主键的表
    这种实现简单,移植性较好 ,需要考虑并发问题,整个系统主键生成都依赖该表,性能影响可能较大

默认主键

  1. 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引;

  2. 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引;

  3. 如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

自增的好处

  1. 数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点);

  2. 如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页;

  3. 如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

扩展

主键尽量采用自增方式,InnoDB 表实际是一棵索引组织表,顺序存储可以提高存取效率,充分利用磁盘空间。
还有对一些复杂查询可能需要自连接来优化时需要用到。

如果没有主键或唯一索引,update/delete 是通过所有字段来定位操作的行,相当于每行就是一次全表扫描。

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值