1.什么是索引?
当我们想要在书中查找某个知识点时 , 通常不会一页一页的去遍历 , 而是在目录中锁定具体位置.这样可以节省大量的时间 , 书中的目录就是充当索引的角色 , 方面我们快速查找书中内容 , 典型的空间换时间的设计思想.
那么转换到数据库中 , 索引就是帮助存储引擎快速获取数据的一种数据结构 , 形象的说:"索引就是数据的目录".
2.索引的分类
提到索引大家可能会想到 , 聚簇索引 , 主键索引 , 二级索引 , 普通索引 , 唯一索引 , hash索引 , B+树索引等等. 要想清楚这些索引的使用和实现方式 , 那么需要根据索引之间的相同特点进行分类.
我们可以按照四个角度来分类索引:
本文主要谈谈按数据结构来分类索引:
MySql中常见按数据结构来分类的索引有 , B+树索引 , Hash索引 , Full-Test索引 , 数据库中每一种存储引擎支持的索引类型不一定相同 , 常见如下图所示:
索引类型 | InnDB 引擎 | MyISAM 引擎 | Memory 引擎 |
B+树 索引 | ✅ | ✅ | ✅ |
Hash 索引 | ❌ | ❌ | ✅ |
Full-Text 索引 | ✅ | ✅ | ❌ |
InnoDB是自MySql 5.5 之后默认存储引擎 , B+树索引也是MySql存储引擎中使用最多的索引类型.
创建表时 , InnoDB存储引擎会根据不同的场景选择不同的列作为索引:
Tips: 其他索引都属于辅助索引(二级索引). 创建的主键索引和二级索引默认使用的是B+树索引.
3.索引的使用场景
索引的最大好处是提高查询速度 , 但索引也是有缺点的 , 例如:
什么时候适合使用索引?
什么时候不需要创建索引?
4.索引的使用
创建主键约束(primary key) , 唯一约束(unique) , 外键约束(foreign key)时 , 会自动创建对应列的索引.
- 查看索引
show index from 表名;
mysql> show index from student;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| student | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
+---------+------------+----------+--------------+-------------+-----------+-------------+-
- 创建索引
对于非主键 , 非唯一性约束 , 非外键的字段可以创建二级索引.
create index 索引名 on 表名(字段名);
mysql> create index name_index on student(name);
mysql> show index from student;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| student | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
| student | 1 | name_index | 1 | name | A | 0 | NULL | NULL | YES | BTREE | | | YES | NULL |
+---------+------------+------------+--------------+-------------+-----------+-------------
Tips:创建索引最好在建表之初 , 如果一个表中已存在很多的数据 , 此时创建索引会占用大量的磁盘盘IO , 花很长的时间 , 在这段时间里数据库无法正常被使用.
- 删除索引
drop index 索引名 on 表名;
mysql> drop index name_index on student;
mysql> show index from student;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| student | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | | YES | NULL |
+---------+------------+----------+--------------+-------------+-----------+-------------+-
Tips:若数据量较大 , 删除索引也会占用大量磁盘导致数据库无法正常使用.
5.索引的数据结构
B+树 vs 哈希表:
提到数据结构 , 第一时间想到的应该是查询时间复杂度为O(1)的哈希表.但哈希表有个致命的缺陷就是无法比较数据的范围 , 只能查询是否相等 , 因此首先排除哈希表.
B+树 vs 二叉搜索树:
说到查询数据的范围 , 二叉树搜索树绝对是一大利器. 但创建索引的初心是提高查询效率 , 如果数据量过大那么二插搜索树的高度会很高 , 因此也会产生多个节点 , 增加数据库的比较次数 , 导致占用大量磁盘影响数据库的性能.
B+树 vs B树:
在二插搜索树的基础上需要进一步优化. 由此引出了B树也就是N插搜索树 , B树最大的好处就是大大降低了树的高度 , 比较次数虽然没有减少 , 但硬盘I/O的次数减少 , 提升了数据库的性能.
虽然B树相比二插搜索树更适合做索引的数据结构 , 但B+树对B树做了更近一步的改进 , 是为索引量身定制的数据结构.
B+树的特点:
eg:我们执行下面这条查询语句:
select * from student where id = 6;
这条语句使用了主键索引查询 id 号为 6 的学生 , 查询过程中B+树会自顶向下逐层查找
数据库的索引和数据都是存放在硬盘中 , 我们可以把读取一个节点当做一个硬盘的I/O操作 , 那么上述查询过程一共经历了 3 个节点 , 也就是进行了 3 次I/O操作.
B+树存储千万级的数据只需要3-4层的高度就可以满足 , 这意味着从千万级别的表中查询目标数据最多需要3-4次磁盘I/O , 所以B+树相较于二叉搜索树 , 最大的优势在于查询效率很高 , 因为即使在数据量很大的情况下 , 查询一个数据的磁盘I/O依然维持在 3-4 次左右.
B+树的优点:
通过二级索引查询数据的过程:
主键索引和二级索引的B+树的区别如下:
如果我们使用二级索引查询 , 会先检验二级索引中B+树的索引值 , 找到对应的叶子节点 , 获取主键值 , 然后再通过主键索引中的B+树查询到对应的叶子节点 , 然后获取整行数据.这个过程叫做回表 , 也就是需要查两次B+树才能查到数据.但如果查询的数据能在二级索引的B+树中查询到 , 这时就不用再查询主键索引了 , 这种在二级索引的B+树中就能查询到结果的过程就叫覆盖索引 , 也就是只要查询一个B+树就能查询到结果.