老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么

又要开始新项目了 , 一顿操作猛如虎 , 梳理流程加画图 。 这不 , 开始对流程及表结构了 。
我:吧啦吧啦吧啦 …… 老大:这个建表为啥还设置个自增 id ?直接用流水号(用户号/产品号)当主键不就行了? 我:这个是 DBA 规定的 , 创建表 id、create_time、update_time 这三个字段都要有 。 《Java 开发规范》也是这么规定的 。小伙伴:(附和)是的 , 规定的是这样的! 老大:流水号在你这是唯一索引吧?设置成主键 , 这样就不用 id 了 , 还减少一次回表查询? 我:…… (说的好像很有道理 , 咱也不敢说话 。 ) 老大:既然他们规定了 , 那你回去查一下为什么要设计个自增 id ? 我:掏出小本本(回去查资料~) 。
老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么文章插图
建表规约
老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么文章插图
在工作中 , 创建表的时候 , DBA 也会审核一下建表 SQL , 检查是否符合规范以及常用字段是否设置索引 。
CREATE TABLE `xxxx` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',`create_time` datetime(3) NOT NULL DEFAULT current_timestamp(3) COMMENT '创建时间',`update_time` datetime(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3) COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_create_time` (`create_time`) USING BTREE,KEY `idx_update_time` (`update_time`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='表注释';复制代码所以在我使用的过程中 , 流水号都是单独设置了一个字段 , 比如叫 trans_no , 但是这次就遇到了疑问:trans_no 既然是唯一的 , 那为什么不直接用 trans_no 当做 id 呢?
下面开始通过查阅相关资料 , 一步一步的了解是为什么?
老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么文章插图
主键什么是主键
老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么文章插图
dev.mysql.com/doc/refman/…
这段定义咱们主要关注最后一句:
When choosing primary key values, consider using arbitrary values (a synthetic key) rather than relying on values derived from some other source (a natural key).
意思是创建主键的时候尽量使用 MySQL 自增主键而不是使用业务生成的值当做主键 。
主键的特征
老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么文章插图
简而言之:
非空、唯一、少更改或不更改。
如何添加主键
老大问:建表为啥还设置个自增 id ?用流水号当主键不正好么文章插图
可以在 create 创建表的时候指定 , 也可以使用 alter 语句后面添加主键 , 不过官方建议在创建表时就指定 。
为什么要添加主键

  1. 主键可以唯一标识这一行数据 , 从而保证在删除更新操作时 , 只是操作这一行数据 。
  2. 索引需要 , 每个 InnoDB 表又有一个特殊的索引 , 即聚簇索引 , 用来存储行数据 。 通常 , 聚簇索引和主键同义 。声明主键 , InnoDB 会将主键作为聚簇索引 。未声明时 , 会在 UNIQUE 所有键列所在位置找到第一个索引 , NOT NULL 并将其作为聚簇索引 未声明且找不到合适的 UNIQUE 索引 , 则内部生成一个隐藏的聚簇索引 GEN_CLUST_INDEX , 这个隐藏的行 ID 是 6 字节且单调增加 。
图 -> 那什么是索引