前言"又要开始新项目了,一顿操作猛如虎,梳理流程加画图。这不,开始对流程及表结构了。我:吧啦吧啦吧啦 ……老大:这个建表为啥还设置个自增 id ?直接用流水号(用户号/产品号)当主键不就行了?我:这个是 DBA 规定的,创建表 id、create_time、update_time 这三个字段都要有。《Java 开发规范》也是这么规定的。小伙伴:(附和)是的,规定的是这样的!老大:流水号在你这是唯一索引吧?设置成主键,这样就不用 id 了,还减少一次回表查询?我:…… (说的好像很有道理,咱也不敢说话。)老大:既然他们规定了,那你回去查一下为什么要设计个自增 id ?我:掏出小本本(回去查资料~)。"


  1  

建表规约

Java 开发手册-嵩山版

在工作中,创建表的时候,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 呢?

下面开始通过查阅相关资料,一步一步的了解是为什么?


  2  

主键

 什么是主键?

MySQL primary key

这段定义咱们主要关注最后一句:

" 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 自增主键而不是使用业务生成的值当做主键。

 主键的特征


简而言之:

非空、唯一、少更改或不更改 。

 如何添加主键


可以在 create 创建表的时候指定,也可以使用 alter 语句后面添加主键,不过官方建议在创建表时就指定。

 为什么要添加主键

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

  3  

索引

这里仅介绍 InnoDB 引擎,具体可以参考官方文档,并且介绍的相对比较简单。

 索引的分类

  1. 聚簇索引:表存储是根据主键列的值组织的,以加快涉及主键列的查询和排序。在介绍主键时也对聚簇索引进行了介绍。
  2. 二级索引:也可以叫辅助索引,在辅助索引中会记录对应的主键列以及辅助索引列。根据辅助索引进行搜索的时候,会先根据辅助索引获取到对应的主键列,然后再根据主键去聚簇索引里面搜索。一般不建议主键很长,因为主键很长辅助索引就会使用更多的空间。

" 补充:
回表:先在二级索引查询到对应的主键值,然后根据主键再去聚簇索引里面取查询。
索引覆盖:二级索引记录了主键列和二级索引列,如果我只查询主键列的值和二级索引列的值,那就不需要回表了。 "

 索引的物理结构

InnoDB 使用的 B+ 数数据结构,根据聚簇索引值(主键/UNQIUE/或者自己生成)构建一颗 B+ 树,叶子节点中存放行记录数据,所以每个叶子节点也可以叫数据页。每个数据页大小默认为 16k,支持自定义。

图:《MySQL 技术内幕 InnoDB 存储引擎》

 数据的插入

当数据插入时,InnoDB 会使页面 1/16 空闲,以备将来插入和更新索引记录。

  1. 顺序插入(升序或降序):会将索引页剩余的大约 15/16 装满
  2. 随机插入:只会使用容量的 1/2 到 15/16

在随机插入中,会频繁的移动、分页,从而造成大量的碎片,并且使索引树不够紧凑。而使用顺序插入的方式,则数据比较紧凑,有更高的空间利用率。

  4  

总结

 Q&A

Q: 什么是回表和索引覆盖?

A:

  1. 回表:先在二级索引查询到对应的主键值,然后根据主键再去聚簇索引里面取查询。
  2. 索引覆盖:二级索引记录了主键列和二级索引列,如果我只查询主键列的值和二级索引列的值,那就不需要回表了。

Q: 为什么要设置自增主键 id ?

A:

  1. 可以唯一标识一行数据,在 InnoDB 构建索引树的时候会使用主键。
  2. 自增 id 是顺序的,可以保证索引树上的数据比较紧凑,有更高的空间利用率以及减少数据页的分裂合并等操作,提高效率。
  3. 一般使用手机号、身份证号作为主键等并不能保证顺序性。
  4. 流水号一般相对较长,比如 28 位,32 位等,过长的话会二级索引占用空间较多。同时为了业务需求,流水号具有一定的随机性。

 相关资料

[1]   MySQL 官方文档:

https://dev.mysql.com/doc/refman/8.0/en/

[2]  《MySQL 技术内幕 InnoDB 存储引擎》第二版

 往期推荐

Doug Lea在J.U.C包里面写的BUG又被网友发现了。

我的程序跑了60多小时,就是为了让你看一眼JDK的BUG导致的内存泄漏。

普通二本,毕业三年,北漂之后,我是怎么成为程序猿的。

hive导数据到mysql 自增主键出错_老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”...相关推荐

  1. 两个datatable合并 主键一样覆盖_MySQL 建表为啥还设置个自增 id ?用流水号当主键不正好么?...

    又要开始新项目了,一顿操作猛如虎,梳理流程加画图.这不,开始对流程及表结构了. 我:吧啦吧啦吧啦 -- 老大:这个建表为啥还设置个自增 id ?直接用流水号(用户号/产品号)当主键不就行了? 我:这个 ...

  2. hive导数据到mysql 自增主键出错_python+mysql做一个图书管理系统?

    开发一个图书管理系统,首先需要对此项目进行一个简单的需求分析: 主要功能包括: 图书信息 图书分类 用户信息 用户借阅统计 管理员 管理员权限 接下来可以进行数据库的设计,在这里我提供一个简单的数据库 ...

  3. hive导数据到mysql 自增主键出错_面试官:MySQL表设计要注意什么?

    本文公众号来源:孤独烟 作者:孤独烟 引言 这篇文章的很多问题,都是面试中实打实会问到的! 比如 OK,具体有下面这些问题 1.为什么一定要设一个主键? 2.你们主键是用自增还是UUID? 3.主键为 ...

  4. sqoop mysql 乱码_请问一下,用sqoop导数据到mysql如果遇到字段编码是utf8mb4的情况怎么处理?...

    我要到的数据其中一个字段里应该是有表情符号,之前数据库的处理是把,字段编码修改成utf8mb4.但现在用sqoop导数据到mysql(对应字段已修改为utf8mb4),却报了如下错误. 谢谢. 15/ ...

  5. sqoop从hive导入数据到mysql时出现主键冲突

    今天在将一个hive数仓表导出到mysql数据库时出现进度条一直维持在95%一段时间后提示失败的情况,搞了好久才解决.使用的环境是HUE中的Oozie的workflow任何调用sqoop命令,该死的o ...

  6. 两台oracle怎样定期导表数据,定期从Oracle导数据至MySQL

    因部分项目需求,需要将Oracle中单表的数据定期导入至MySQL,注意此处对数据的时效性要求不高.要求高可以利用goldengate 首先,需要将visit表中的vid,userid,goodid, ...

  7. hive mysql互导_利用Sqoop实现Hive的数据与MySQL数据的互导

    1. 配置概览 Hive arguments: --create-hive-table Fail if the target hive table exists --hive-database Set ...

  8. 使用kettle从mongodb导数据到mysql记录

    kettle 最近需要将mongodb的部分表导入到MySQL中,学习使用了kettle,记录一下 安装 1.安装jdk 2.解压kettle 3.将MySQL的驱动放到安装目录(D:\data-in ...

  9. mysql 建表_别再胡乱建表了,看看阿里P8总结的mysql建表规约吧

    (一) 建表规约 [强制]表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint ( 1表示是,0表示否). 说明:任何字段如果为非负数,必须是 uns ...

最新文章

  1. 学术 科研 论文写作 生物信息学
  2. 全景视频的跟踪与合成方法
  3. boot spring 怎么执行hql_彻底透析SpringBoot jar可执行原理
  4. Spring Clould负载均衡重要组件:Ribbon中重要类的用法
  5. 【技术史】数据中台的前世今生
  6. 设计模式原则(3)--Dependency Inversion Principle(DIP)--依赖倒转原则
  7. 【干货】如何删除“自豪地采用WordPress“
  8. android mvp_Android MVP
  9. html 富文本编辑器相关--向编辑器内部插入文字图片等各种dom元素 通用方法
  10. Atitit 代码之美读后感目录内容简介 · · · · · · 1目录 1作者简介 · · · · · · 2ati评价案例法总结 内容简介 · · · · · ·《
  11. 三星k3梅林没有软件中心_斐讯K3梅林软件中心版刷机包 修正WAN口 修正2.4G 自动息屏 完美混血...
  12. iPhone 各屏幕尺寸及解析
  13. hprose for php,hprose for php
  14. 读书笔记-人月神话8
  15. 区块链开发语言python_区块链开发语言有哪些?哪种语言更适合区块链开发?
  16. ESP32-CAM与Tonny搭建问题。
  17. 关于jetson 的一堆奇怪bug的修复之路(同时解决sdkmanger升级/安装tensorrt提示密码错误,无法打开terminal)
  18. Python实现的双目相机标定系统
  19. 《斗罗大陆H5》月刃武魂指导和魂环搭配
  20. Solved: ERROR: Failed building wheel for hdbscan

热门文章

  1. 关于sigma pix的理解
  2. pyqt5获取屏幕大小并将窗口大小设置为屏幕的百分之六十
  3. 最应该看的一本人工智能理论的书-神经网络于深度学习-目录
  4. sticky list item
  5. 亚信产业互联网生态亮相2016南京软博会
  6. 【加密解密】单表加密(Javascript实现)
  7. selenium借助AutoIt识别上传(下载)详解
  8. 安装Vertica数据库
  9. Exchange2007中创建和访问公用文件夹
  10. Android原生(Native)C开发之二 framebuffer篇