面试之建议MYSQL表建主键,并且推荐使用整形的自增主键?

参考:https://blog.csdn.net/a6686039/article/details/89019666
https://blog.csdn.net/m0_45406092/article/details/111940017

注意:入文之前,先彻底了解聚集索引和非聚集索引

一、聚集索引和非聚集索引

一 . 聚集索引的形成:
InnoDB引擎要求表必须有主键(MyISAM可以没有),innodb会按照如下规则进行处理:
  1,如果一个主键被定义了,那么这个主键就是作为聚集索引
  2,如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引
  3,如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。
  
二. 聚集索引数据结构模:
在这里插入图片描述
我们知道InnoDB采用B+树作为存储结构

①由于B+树的内部节点只存放键,不存放值,因此,一次读取,可以在内存页中获取更多的键,有利于更快地缩小查找范围。

②B+树的叶节点由一条链(双向指针)相连,因此,当需要进行一次全数据遍历的时候,B+树只需要使用O(logN)时间找到最小的一个节点,然后通过链进行O(N)的顺序遍历即可(有利于范围查找)。而B树则需要对树的每一层进行遍历,这会需要更多的内存置换次数,因此也就需要花费更多的时间

三.非聚集索引和聚集索引的区别:
非聚集索引和聚集索引一样, 同样是采用平衡树作为索引的数据结构。索引树结构中各节点的值来自于表中的索引字段, 假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引 , 那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。 如下图
在这里插入图片描述
每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。所以索引不是建立越多越好的。

非聚集索引和聚集索引的区别在于, 通过聚集索引可以查到需要查找的数据, 而通过非聚集索引可以查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据,如下图
在这里插入图片描述
从上图可以看出非聚集索引都是要根据存储的主键值通过聚集索引,定位到数据,聚集索引(主键)是通往真实数据所在的唯一路径。

然而, 有一种例外可以不使用聚集索引就能查询出所需要的数据,那就是覆盖索引(联合索引)。当为字段建立索引以后, 字段中的内容会被同步到索引之中。这种方式就不用经过聚集索引拿到数据。

二、为什么建议InnoDB必须建主键

I nnoDB引擎要求表必须有主键(MyISAM可以没有),innodb会按照如下规则进行处理:
1.如果一个主键被定义了,那么这个主键就是作为聚集索引
2.如果没有主键被定义,那么该表的第一个唯一非空索引被作为聚集索引
3.如果没有主键也没有合适的唯一索引,那么innodb内部会生成一个隐藏的主键作为聚集索引,这个隐藏的主键是一个6个字节的列,改列的值会随着数据的插入自增。

这是上面讲述到的, 聚簇索引默认是主键。如果表中没有定义主键,InnoDB 会选择一个唯一的非空索引(确切说会选择一个唯一非空的列作为主键)代替。如果没有这样的索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增)。**即会隐式定义一个主键来作为聚簇索引。
这种让InnoDB去操作,更何况那个非空的列是什么复杂的结构,会不会造成影响其性能,所以我们能手动去建立整型自增的,为啥还要麻烦InnoDB呢?

三、为什么推荐使用整型的自增主键

Innodb中的每张表都会有一个聚集索引,而聚集索引又是以物理磁盘顺序来存储的,自增主键会把数据自动向后插入,避免了插入过程中的聚集索引排序问题。聚集索引的排序,必然会带来大范围的数据的物理移动,这里面带来的磁盘IO性能损耗是非常大的。
而如果聚集索引上的值可以改动的话,那么也会触发物理磁盘上的移动,于是就可能出现page分裂,表碎片横生。

Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率

或者

聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。

聚簇索引的顺序和磁盘中数据的存储顺序是一致的,如果主键不是自增id,那么可以想 象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一 页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

附:

  • 主键递增,数据行写入可以提高插入性能,可以避免page分裂,减少表碎片提升空间和内存的使用 主键要选择较短的数据类型,
  • Innodb引擎普通索引都会保存主键的值,较短的数据类型可以有效的减少索引的磁盘空间,提高索引的缓存效率

猜你喜欢

转载自blog.csdn.net/weixin_42754971/article/details/113636280
今日推荐