本篇关键词

关键词

解释

聚簇索引

主键索引的叶子节点存的是整行数据,在InnoDB里,主键索引也称为聚簇索引

二级索引

非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引

回表

先通过普通查询得到主键,再由主键查询得到具体值的过程

覆盖索引

普通索引能够查询到的需要的数据,从而不需要再回表查询,那么就是覆盖索引

索引下推

索引遍历过程中,对索引包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表的次数

最左前缀

在联合索引时,满足联合索引第一个字段的查询也可以进行索引加速,称为最左前缀

1.索引常见模型

哈希表、有序数组和搜索树

1.1 哈希表

哈希表是一种以键-值(key-value)存储数据的结构,我们只要输入待查找的值即key,就可以找到其对应的值即Value。哈希的思路很简单,把放在数组里,用一个哈希函数把key换算成一个确定的位置,然后把 value 放在数组的这个位置。

不可避免地,多个key值经过哈希函数的换算,会出现同一个值的情况。处理这种况的一种方法是,拉出一个链表。

哈希表这种结构适用于只有等值查询的场景,比如Memcached及其他一些NoSQL 引擎。

1.2 有序数组

有序数组在等值查询和范围查询场景中的性能就都非常优秀, 但是有序数组索引只适用于静态存储引擎

1.3 搜索树

查询速度和更新速度都是O(log(N))

2. InnoDB的索引模型

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

对于没有主键的表,InnoDB会默认创建Rowid做主键

假如有一个表: 主键列为 ID ,表中有字段 k,并且在 k 上有索引。

建表语句

mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;

表中 R1~R5 的 (ID,k) 值分别为 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6),两棵树
的示例示意图如下。

hash mysql 函数 mysql计算哈希值_联合索引

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

主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引
(clustered index)。

非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引
(secondary index)。

2.1 基于主键索引和普通索引的查询区别:

如果语句是 select * from T where ID=500,即主键查询方式,则只需要搜索 ID 这棵
B+ 树;

如果语句是 select * from T where k=5,即普通索引查询方式,则需要先搜索 k 索引
树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表

2.2 覆盖索引

如果执行的语句是select ID from T where k between 3 and 5,这时只需要查 ID 的
值,而 ID 的值已经在 k 索引树上了,因此可以直接提供查询结果,不需要回表。也就是
说,在这个查询里面,索引 k 已经“覆盖了”我们的查询需求,我们称为覆盖索引

2.3 最左前缀

市民表:

CREATE TABLE `tuser` (
`id` int(11) NOT NULL,
`id_card` varchar(32) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`ismale` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_card` (`id_card`),
KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB

假如在这个市民表上,查询满足姓”李“的人,同时姓名和年龄是联合索引, 那么查询SQL语句"select * from tuser where name like ‘张%’" 也可以使用上索引进行加速

所以,在建立联合索引时,可以考虑索引内的字段顺序,第一原则是,如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。, 第二个原则就是考虑空间, 像这种(name, age)的联合索引,使用(name, age) 、 (age)两个索引来满足名称和名称年龄,年龄查询是比(age, name)、(name)这种联合索引要节省空间的

2.4 索引下推

市民表上,新增一个需求,名字第一个字是张,而且年龄是 10 岁的所有男孩, SQL语句select * from tuser where name like '张 %' and age=10 and ismale=1;

这个时候,使用索引前缀假如能够得到满足条件的记录ID3。在MySQL5.6之前,只能从ID3开始一个个回表。到主键索引上找出数据行,再对比字段值。

而在Mysql5.6之后,引入了索引下推优化,可以在索引遍历过程中,对索引包含的字段先做判断,直接过滤掉不满足条件的记录,减少了回表的次数。

无索引下推,和有索引下推的过程

hash mysql 函数 mysql计算哈希值_主键_02

hash mysql 函数 mysql计算哈希值_联合索引_03