你真的懂数据库的索引吗?MySql索引详谈

你真的懂数据库的索引吗?MySql索引详谈

索引在数据库中是一个绝对重点的概念,也是面试中必问的知识点,必须深入学习一下

我们选取Mysql的索引来好好研究下

先来看看官方是如何定义索引的:

  • 索引(Index)是帮助 MySQL 高效获取数据的数据结构

所以,我们可以说,索引是一种数据结构,那么是什么数据结构呢?Mysql给出的答案是B+树
B+树是B树的延申,树我们知道,在构建树的时候,是会进行一个排序并进行平衡处理的,所以,我们得到索引就是排好序的数据结构,对于有序的数据结构,必定是二分查找,这种数据结构与算法大幅加快了数据库的查找速度

此处请记好索引都是排过序

下图就是一种可能的索引(二叉树)

假设我们某张表的每行记录只有两个字段(col1-id col2-age)

  • 左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址。为了加快 Col2 的查找,可以维护一个右边所示的二叉查找树,该二叉树节点存储col2的值,每个节点分别包含索引键值和一个指向对应数据记录(某一行的所有字段数据)物理地址的指针(这也称为非聚簇索引,如果直接存储的是记录,称聚簇索引

  • 这样就可以运用 二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录(一行称为一条记录

  • 一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上

  • 该索引使用数据作为索引键,而非主键

使用索引优缺点

优点:

  • 提高检索效率,降低IO成本
  • 索引列对数据排序,降低数据排序成本,降低CPU消耗

缺点:

  • 降低更新表速度,因为更新表时同时要更新索引
  • 索引保存了主键与索引字段,并有指向实体表的指针,也会占用空间

B Tree

我们着重研究Mysql的B+树索引,轻视哈希索引

研究B+树之前,我们先看看B树是如何存储索引的

  • 浅蓝色为磁盘块,包含深蓝的数据项与黄色的指针
  • 两个数据项配备三个指针,P1表示小于第一个数据项的,P2表示在第一个数据项和第二个数据项之间的,P3表示大于第二个数据项的
  • 真实的数据在最底下那一排磁盘块(每个深蓝代表一条行记录或指向记录的指针)

查找过程

以查找29为例

  1. 磁盘块1读入内存,此时一次IO
  2. 二分查找锁定磁盘块1的P2指针
  3. 把P2指向的磁盘块3读入内存,此时二次IO
  4. 二分查找锁定磁盘块3的P2指针
  5. 把磁盘块3的P2指向的磁盘块3读入内存,此时三次IO
  6. 找到29的行记录,结束查找,共3次IO

B+ Tree

来看看B+树是如何存储主键索引的

可以明显看见,每个磁盘块不止两个数据项和三个指针了,而是进行了扩展,那么我们可以得到

  • 该B+ Tree存储主键的索引,表中有主键时自动创建该索引

  • B+树每个节点可以包含更多的节点,树的高度大幅降低

  • 数据范围变为多个区间,区间越多,检索速度越快

  • 非叶子节点存储主键,叶子节点存储主键和值(记录或记录的物理地址)

  • 叶子节点两两指针互连,也就提高了顺序查询的性能更高(在最下面一层顺序查找)

  • 实际情况中,3~4层足以支撑千万到亿级别的记录了

来看看InnoDB引擎版本的B+树

  • InnoDB通过B+Tree结构对主键创建索引,称为主索引,叶子节点存储记录,
  • InnoDB必然通过Key(可以是主键、唯一键、自动生成的rowid)对数据进行存储
  • 如果无主键,就用唯一键,如果无唯一键,就自动生成6位rowid做唯一标识
  • 在InnoDB引擎下,如果创建索引的键是其他字段而不是主键,那么在该字段的叶子节点中不存储直接的记录,存储的是该记录的主键,然后再通过主键索引找到对应的记录,称为回表

聚簇索引

聚簇索引是innodb数据引擎支持的索引,而Myisam并不支持聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式
如下图,左侧的索引就是聚簇索引,key在磁盘的排列和索引排序保持一致,且记录直接与键值保存在一起

聚簇的好处:

  • 查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不不用从多个数据块中提取数据,所以节省了大量的io操作

聚簇的限制

  • 由于数据物理存储排序方式只能有一种,所以每个Mysql的表只能有一个聚簇索引。一般情况下就是该表的主键

  • 为了充分利用聚簇索引的聚簇的特性,所以innodb表的主键列尽量选用有序的顺序id,而不建议用无序的id,比如uuid这种

非聚簇索引

叶子节点存储的是指向记录的指针,而非直接是记录

索引分类

单值索引

一个索引只包含单个列,一个表可以有多个单列索引

CREATE INDEX idx_customer_name ON customer(customer_name);

唯一索引

索引列的值必须唯一,但允许有空值

CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);

主键索引

设定为主键后数据库会默认自动建立索引,以上的B+树就是说明InnoDB自动创建的索引,innodb为聚簇索引

复合索引/组合索引

即一个索引包含多个列

CREATE INDEX idx_no_name ON customer(customer_no,customer_name);

索引创建时机

  • 主键自动建立唯一索引
  • 频繁作为查询条件的字段
  • 查询中与其他表关联的字段应该建立索引
  • 组合索引性价比更高
  • 排序的字段:若已排序的字段通过索引去访问,速度大增
  • 查询中统计或分组的字段

以下情况不适合做索引

  • 表记录太少
    • InnoDB的回表机制会对非主索引的查找走两次B+树,反而更慢
select * from table where name = `zz` ; 
select id from table where name = `zz` ; ` 

第一条语句需要走回表
第二条语句走不需要走回表,因为非主索引InnoDB叶子节点存放的就是id
不需要走回表这个过程叫索引覆盖

  • 经常增删改查的字段
  • where条件里用不到的字段
  • 过滤性差的字段
发布了182 篇原创文章 · 获赞 121 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/JunSIrhl/article/details/105625939