从头开始搞懂 MySQL(04)索引(上)

Posted 思想累积

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从头开始搞懂 MySQL(04)索引(上)相关的知识,希望对你有一定的参考价值。

1、常见索引

我们学习数据库时肯定会提到索引,或者在日常工作中,如果有一个慢 SQL,分析原因后,我们可能就会说给某个字段加个索引。索引到底是什么东西呢?

索引是为了提高数据查询的效率,就像书的目录一样,在不看目录的情况下,我们想要找到一本书里面的内容,可能需要从头开始翻很久才能找到,有了目录之后,我们才能轻易找到想要的内容

1.1 常见索引结构

  • 哈希

    哈希是一种以 (key - value)键值对存储的数据结构,哈希结构和实现请看这里:哈希表

    哈希表这种结构适用于等值查询的场景,可以直接通过 key 来查询,但哈希表不是有序的,所以如果使用哈希索引进行区间查询的话速度比较慢

  • 有序数组

    有序数组在等值查询和范围查询的时候都比较适用,有序数组查询效率较高,可以通过 二分查找 来快速找到,但是更新数据比较麻烦,所以有序数组索引适用于静态存储引擎,对于一些不会更改的历史数据可以考虑使用有序数组索引

  • 二叉树的特点是每个节点的左节点小于父节点,父节点小于右节点。树可以有多叉,多叉树是每个节点有多个子节点,子节点大小保证从左到右递增,但实际上的数据库存储并不使用二叉树,因为我们无法保证树的高度,树越高每次查询数据读磁盘次数就越多,我们不应该使用二叉树,而应该使用多叉树

mysql 中,索引是在存储引擎层面实现的,所以没有统一的索引标准,不同存储引擎的索引的工作方式并不一致。InnoDB 使用较为广泛,所以我们还是用 InnoDB 举例,分析 InnoDB 引擎的索引

2、InnoDB 索引

在 InnoDB 引擎中,表都是根据主键顺序以索引的形式存放,这种存储方式的表称为索引组织表。InnoDB 使用了 B+ 树索引模型,所以数据也都是存储在 B+ 树中的

每个索引在 InnoDB 中对应一颗 B+ 树

以下例建表 SQL 为例:

create table test (

id int primary key,

card int not null,

name varchar(20),

index (card)

)engine=InnoDB;

表中有两个索引 id 和 card,表中有四行数据,值分别为(50, 12234)、(100, 13829)、(150, 14272)、(200, 52349)索引结构如下:

根据叶子节点的内容,索引类型分为主键索引非主键索引

主键索引的叶子结点存放的是整行数据,主键索引也被称之为聚簇索引(clustered index)

非主键索引叶子节点存放主键的值,非主键索引称为耳机索引(secondary index)

2.1主键索引和普通索引的查询有什么区别

  • 如果通过主键查询,name只需要搜索 ID 这颗 B+ 树
  • 如果通过普通索引查询,需要先搜索 card 这个索引树,然后得到 ID 的值,再到 ID 索引树搜索一次

先通过普通索引查询到主键索引,再用主键索引去主键索引树查询,这个过程称为回表,也就是说,基于非主键索引的查询需要多扫描一张索引树,所以我们在编写 SQL 中应该尽量使用主键来查询

3、索引维护

索引是需要维护的,在插入新的值的时候,以上图为例,如果插入新的 ID 值为 300,只需要在 row4 后面再加入一个新的记录

如果插入的值为 180,逻辑上需要挪动200,空出位置,更糟糕的是如果后面的数据页满了的话,按照 B+ 树的算法,会申请一个新的数据页,挪动部分数据过去,这样性能肯定会收到影响。而且页分裂也会影响到数据页的利用率。如果删除了数据,数据页也会做合并操作,可以视为分裂过程的逆向操作

3.1 什么情况下使用自增主键

一般情况下,一些建表规范里面要求建表语句里面一定要有自增主键

自增主键是指在自增列上定义的主键,建表语句中为:NOT NULL PRIMARY KEY AUTO_INCREMENT

有了自增主键后,插入新的记录的时候可以不指定主键的值,默认会对当前主键最大值加 1 作为新增记录的主键

如果使用了自增主键,每次插入对索引树来说都是追加操作,不会挪动其它记录,也不会触发叶子结点分裂

主键长度越小,普通索引的叶子结点就越小,普通索引所占的空间就越小,从性能和存储空间来说,自增主键更为合理

如果只有一个索引,我们就不用考虑其它索引叶子结点大小的问题,我们将这个索引设置为主键,直接使用主键查询。

3.2 删除&重建索引

  • 对于非主键索引,只需要删除并重建对应的非主键索引即可
  • 对于主键索引重建,先重建主键索引,然后把所有的非主键索引重新建一遍

以上是关于从头开始搞懂 MySQL(04)索引(上)的主要内容,如果未能解决你的问题,请参考以下文章

从头开始搞懂 MySQL(06)索引的选择

从头开始搞懂 MySQL(06)索引的选择

从头开始搞懂 MySQL(05)行锁表锁全局锁

从头开始搞懂 MySQL(05)行锁表锁全局锁

从头开始搞懂 MySQL(08)count(*) 很慢怎么办

索引很难么?带你从头到尾捋一遍MySQL索引结构,不信你学不会!