索引
索引是存储引擎用于 提高数据库表的访问速度的一种数据结构,它为特定的 mysql 字段进行一些特定的算法排序,比如二叉树的算法和哈希算法
- 哈希算法是通过建立特征值,然后根据特征值来快速查找。
- 用的最多,并且是 mysql 默认的就是二叉树算法 BTREE(B+ 树),通过 BTREE 算法建立索引的字段,比如扫描 20 行就能得到未使用 BTREE 前扫描了 2^20^ 行的结果。
索引的使用场景
索引的优缺点
优点
- 加快数据查找的速度
- 为用来排序或分组的字段添加索引,可以加快分组和排序的速度
- 加快表与表之间的连接
缺点
- 建立索引需要占用物理空间
- 会降低表的增删改的效率,因为每次对表记录进行增删改,需要进行动态维护索引,导致增删改时间变长
什么情况下需要建索引
- 经常用于查询的字段
- 经常用于连接的字段建立索引,可以加快连接的速度
- 经常需要排序的字段建立索引,因为索引已经排好序,可以加快排序查询速度
什么情况下不建索引
where
条件中用不到的字段不适合建立索引- 表记录较少。比如只有几百条数据,没必要加索引。
- 需要经常增删改。需要评估是否适合加索引
- 参与列计算的列不适合建索引
- 区分度不高的字段不适合建立索引,如性别,只有男/女/未知三个值。加了索引,查询效率也不会提高。
索引的数据结构
B+ 树索引
B+ 树是基于 B 树和叶子节点顺序访问指针进行实现,它具有 B 树的平衡性,并且通过顺序访问指针来提高区间查询的性能。
在 B+ 树中,节点中的 key
从左到右递增排列,如果某个指针的左右相邻 key
分别是 keyi 和 keyi+1,则该指针指向节点的所有 key
大于等于 keyi 且小于等于 keyi+1。
进行查找操作时,首先在根节点进行二分查找,找到 key
所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key
所对应的数据项。
MySQL 数据库使用最多的索引类型是 BTREE
索引,底层基于 B+ 树数据结构来实现。
mysql> show index from blog\G;
*************************** 1. row ***************************
Table: blog
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: blog_id
Collation: A
Cardinality: 4
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
Visible: YES
Expression: NULL
哈希索引
哈希索引是基于哈希表实现的,对于每一行数据,存储引擎会对索引列进行哈希计算得到哈希码,并且哈希算法要尽量保证不同的列值计算出的哈希码值是不同的
将哈希码的值作为哈希表的 key 值,将指向数据行的指针作为哈希表的 value 值。这样查找一个数据的时间复杂度就是 O(1),一般多用于精确查找。
Hash 索引和 B+ 树索引的区别?
- 哈希索引不支持排序,因为哈希表是无序的。
- 哈希索引不支持范围查找。
- 哈希索引不支持模糊查询及多列索引的最左前缀匹配。
- 因为哈希表中会存在哈希冲突,所以哈希索引的性能不稳定,而 B+ 树索引的性能是相对稳定的,每次查询都是从根节点到叶子节点。
为什么 B+ 树比 B 树更适合实 现数据库索引?
- 由于 B+ 树的数据都存储在叶子结点中,叶子结点均为索引,方便扫库,只需要扫一遍叶子结点即可,
- 但是 B 树因为其分支结点同样存储着数据,我们要找到具体的数据,需要进行一次中序遍历按序来扫
- 所以 B+ 树更加适合在区间查询的情况,而在数据库中基于范围的查询是非常频繁的,所以通常 B+ 树用于数据库索引。
- B+ 树的节点只存储索引 key 值,具体信息的地址存在于叶子节点的地址中。这就使以页为单位的索引中可以存放更多的节点。减少更多的 I/O 支出。
- B+ 树的查询效率更加稳定,任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。