• 浅析阿里规范中为什么要求表必须有主键id:不建主键id会有什么影响


    一、问题背景

      今天在设计表结构的时候,有个记录表只需要记录下是谁得了什么东西,什么时间得的,也就是3个字段:user_id、medal_id、created_time,通常表也会加主键 id,但是这个表其实不怎么用到,也就是查询谁的记录,或者某东西的记录时会关联查一下。你看都没有 主键id 啥事,所以我就有了个疑问,不加 id, 表不是就会小一点吗,那像这种情况到底需不需要加主键id呢?什么情况下不需要建主键id、建与不建的好处各是啥呢?

    二、阿里规范中为什么要求表必须有主键id

      数据库会默认为主键字段创建索引【主键索引】。

      那么如果表中具有多个主键,数据库会不会为每个主键都创建索引呢?先建一张表【user:两个主键id,name】

    CREATE TABLE `user`  (
      `id` int NOT NULL,
      `name` varchar(255) NOT NULL,
      PRIMARY KEY (`id`, `name`)
    );
    -- 运行命令查看索引
    show index FROM user

      可以看到:数据库为 id 和 name 都创建了索引。现在终于有点明白阿里规范中为什么要求创建主键id了。但是还是有疑问:那么难道仅仅只是创建了索引的区别吗?很多表查询不用索引查询,数据量小时,影响也并不大,那么如果不建主键 id 会有什么影响呢?

    三、MySQL InnoDB数据表缺少主键会怎样

    1、问题

      MySQL数据表使用InnoDB作为存储引擎的时候,数据结构就是使用B+树,而数据本身存储在主键索引上,也就是通常所说的聚簇索引,也就是每个表都需要有个聚簇索引树,但是,在建表的时候却发现可以不用指定主键,那么MySQL对于没有指定主键的表示如何处理的呢?

    2、InnoDB索引

      对于InnoDB,可以简单地把所有数据视为索引,每一个索引都对应一个B+数,而主键对应的索引就是聚簇索引,表的所有数据都存储在聚簇索引上,而除了聚簇索引的普通索引存储的只是主键的引用,所以,查询的时候对于普通索引需要进行回表才能取到具体数据

    3、缺少主键MySQL如何处理

      既然InnoDB对数据的存储必须依赖于主键,那么对于没有创建主键的表,该怎么办?

      InnoDB对聚簇索引处理如下:

    (1)如果定义了主键,那么InnoDB会使用主键作为聚簇索引

    (2)如果没有定义主键,那么会使用第一非空的唯一索引(NOT NULL and UNIQUE INDEX)作为聚簇索引

    (3)如果既没有主键也找不到合适的非空索引,那么InnoDB会自动生成一个不可见的名为ROW_ID的列名为GEN_CLUST_INDEX的聚簇索引,该列是一个6字节的自增数值,随着插入而自增

      很明显,缺少主键的表,InnoDB会内置一列用于聚簇索引来组织数据。而没有建立主键的话就没法通过主键来进行索引,查询的时候都是全表扫描,小数据量没问题,大数据量就会出现性能问题。

      但是,问题真的只是查询影响吗?不是的,对于生成的ROW_ID,其自增的实现来源于一个全局的序列,而所有以ROW_ID为主键的表均共享该序列,这也意味着插入的时候生成需要共享一个序列,那么高并发插入的时候为了保持唯一性就避免不了锁的竞争,进而影响性能。

    4、缺少主键或者非空索引存在问题

    (1)使用不了主键索引,查询会进行全表扫描

    (2)影响数据插入性能,插入数据需要生成ROW_ID,而生成的ROW_ID是全局共享的,并发会导致锁竞争,影响性能

    5、为每个表设置主键

      既然知道InnoDB对数据的存储和处理都是基于聚簇索引的,那么,在建表时候要注意主键的重要性,为每个表都设置一个主键,如果没有合适的字段来作为主键,可以设置一个业务无关的的代理主键,可以是自增ID,也可以是UUID(建议使用自增ID,性能较好)。

    6、总结:

      在理解InnoDB的数据结构之后,自然而然就会知道主键的重要性,在建表的时候也不会忘记设置主键,无论表设计有无合适的唯一字段,都需要设置一个主键,提高性能的同时也是一种好的习惯,对于后续的拓展以及表之间关联都有一定的拓展性。

  • 相关阅读:
    解决运行docker命令要用sudo的问题
    python3 http.server 本地服务支持跨域
    Linux 命令速记本
    截取某段时间内的日志
    centos7 安装postgresql10
    centos 7 安装 mail
    centos7 mail
    centos7 mysql 5.7 官网下载tar安装
    修改storm ui 默认端口
    redis-trib构建集群
  • 原文地址:https://www.cnblogs.com/goloving/p/15951619.html
Copyright © 2020-2023  润新知