• 数据库主键一定要自增的吗?有哪些场景下不建议自增?


    我们平时建表的时候,一般会像下面这样。

    CREATE TABLE `user` (
      `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
      `name` char(10) NOT NULL DEFAULT '' COMMENT '名字',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    出于习惯,我们一般会加一列id作为主键,而这个主键一般边上都有个AUTO_INCREMENT, 意思是这个主键是自增的。自增就是i++,也就是每次都加1。

    但问题来了。

    主键id不自增行不行?

    为什么要用自增id做主键?

    离谱点,没有主键可以吗?

    什么情况下不应该自增?

    被这么一波追问,念头都不通达了?

    这篇文章,我会尝试回答这几个问题。

    主键不自增行不行

    当然是可以的。比如我们可以把建表sql里的AUTO_INCREMENT去掉。

    CREATE TABLE `user` (
      `id` int NOT NULL COMMENT '主键',
      `name` char(10) NOT NULL DEFAULT '' COMMENT '名字',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后执行

    INSERT INTO `user` (`name`)  VALUES	('debug');
    
    • 1

    这时候会报错Field 'id' doesn't have a default value。也就是说如果你不让主键自增的话,那你在写数据的时候需要自己指定id的值是多少,想要主键id是多少就写多少进去,不写就报错。

    改成下面这样就好了

    INSERT INTO `user` (`id`,`name`)  VALUES	(10, 'debug');
    
    • 1

    为什么要用自增主键

    我们在数据库里保存的数据就跟excel表一样,一行行似的。

    而在底层,这一行行数据,就是保存在一个个16k大小的页里。

    每次都去遍历所有的行性能会不好,于是为了加速搜索,我们可以根据主键id,从小到大排列这些行数据,将这些数据页用双向链表的形式组织起来,再将这些页里的部分信息提取出来放到一个新的16kb的数据页里,再加入层级的概念。于是,一个个数据页就被组织起来了,成为了一棵B+树索引

    而当我们在建表sql里声明了PRIMARY KEY (id)时,mysql的innodb引擎,就会为主键id生成一个主键索引,里面就是通过B+树的形式来维护这套索引。

    到这里,我们有两个点是需要关注的:

    • 数据页大小是固定16k
    • 数据页内,以及数据
  • 相关阅读:
    应用层Buffer缓冲区及其重要性
    第二章——操作数据库
    SwiftUI 4.0 (iOS 16) 新ViewThatFits视图使用简介
    kafka日志文件详解及生产常见问题总结
    操作系统知识点-处理机调度
    Tableau4——标靶图,甘特图,瀑布图
    第十一章 JavaScript操作DOM对象
    为什么list.sort()比Stream().sorted()更快?
    获得1688商品评论 API 返回值说明
    MyBatis缓存机制
  • 原文地址:https://blog.csdn.net/Huangjiazhen711/article/details/127984669