什么是索引
- 在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。(百度百科)
- 索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
- 索引是在存储引擎层实现的, 所以并没有统一的索引标准, 即不同的存储引擎的索引工作方式并不一样, 而即时多个存储引擎都支持同一种类型的索引, 其底层的实现也可能不同
索引的作用 :
- 索引的出现就是为了提高数据查询的效率, 就像书的目录一样
索引的优点
- 索引会让我们的查询次数降低, 实质层面上也就减少了 IO 操作, 因为 IO 操作相当费时
- 帮助服务器避免分组和排序, 因为索引在数据结构层面上, 已经有排序和分组的特征
- 稳定性 : 将随机的 IO 变成顺序性的 IO , B+索引会将相邻的数据节点放在一起
索引的适合范围 / 使用场景
- 索引在小数据量的数据库中, 发挥的作用并不大, 因为创建索引也是一定程度上增加了空间复杂度, 大部分建立全表扫描要比建立索引更加高效
- 在中型数据量的数据库上可以加索引, 因为这个可以大幅度提升数据的拆线呢效率
- 大型数据量的数据库上, 不仅需要索引, 也可考虑建立分库分表技术来缓解数据库的压力
索引的模型
-
哈希表 : 是一种 键 - 值 ( key - value ) 存储数据的结构
- 思路 : 把值放在数组里, 用一个哈希函数把 key 换算成一个确定的位置, 然后把 value 放在数组的这个位置
- 缺点 : 做区间查询的速度很慢
- 使用场景 : 等值查询的场景, 对范围查询无能为力
- Memcached 以及其他 一些 NoSQL
-
有序数组
- 以 Key 的递增顺序保存数据在数组中, 有序数组在等值查询和范围查询场景中的性能就都非常优秀
- 缺点 : 在更新数据的时候, 移动数据成本太高
- 使用场景 : 只适用静态存储引擎
-
搜索树
- 二叉搜索树, 也称为二叉查找树、有序二叉树或排序二叉树
- 二叉搜索树相比于其它数据结构的优势在于查找、插入的时间复杂度较低,为 O(log(n))。为了维持 O(log(n))的查询复杂度,需要保持这棵树是平衡二叉树
- 查询效率 O( log(N) )
-
n 叉树
-
B+ 树
-
优点 :
- 层级更低,IO 次数更少
- 每次都需要查询到叶子节点,查询性能稳定
- 叶子节点形成有序链表,范围查询方便
-
操作算法 :
- 查找 - > 由根节点自顶向下遍历树,根据分离值在要查找的一边的指针;在节点内使用二分查找来确定位置。
- 插入
- 删除
-
MySQL 中索引种类
- B+tree 索引是目前大多数 MySQL 默认索引方式, 索引又分为聚簇索引和 非聚簇索引, 聚簇索引是一个记录着数据的索引节点, 非聚簇索引是存着主键 id, 再由 id 去寻找真实数据
- 哈希索引 : 哈希索引是查找速度极快的索引, 其时间复杂度能达到 O(1), 但是由于是 hash 策略实现的, 所以不支持排序和分组, 只支持精确查找, 不支持范围查找
- 全文索引 : InnoDB 不支持全文检索, MyISAM 支持全文索引, 记录着关键字到文献的映射
- 空间数据索引 : 支持空间纬度上的索引机制, GIS 相关
InnoDB 的索引模型
- 在 InnoDB 中, 表都是根据主键顺序一索引的形式存放的, 这种存储方式的表成为哦索引组织表, InnoDB 适用了 B+ 树索引模型, 所以数据都是存储在 B+ 树中的
- 每一个索引在 InnoDB 中都对应一颗 B+ 树
#建表语句
mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;
- 两种索引
- 索引分类 : 根据叶子节点的内容, 索引类型分为主键索引和非主键索引
- 主键索引
- 主键索引的叶子节点存放的是整行数据
- 在 InnoDB 中, 主键索引也被称为聚簇索引 ( clustered index )
- 非主键索引
- 非主键索引的叶子节点内容是主键的值
- 在 InnoDB 中, 非主键索引也被称为二级索引 ( secondary index )
- 主键索引 和 普通索引 区别
- SQL : select * from T where ID = 500 , 即主键查询方式, 则只需要搜索 ID 这颗 B+ 树;
- SQL : select * from T where k = 5, 即普通索引查询方式, 则需要先搜索 k 索引树, 得到 ID 的值 500, 再到 ID 索引树搜索一次, 再得到结果, 这个过程称为 回表
- 基于非主键的搜索的查询需要多扫描一颗索引树, 因此我们应当尽量适用主键索引
B+ Tree 的特性 :
- 索引底层使用的是 B+tree 数据结构, 这种结构可以大幅度提升查询性能, 因为 B+tree 底层是由叶子节点组成的单向列表, 塑造出它的稳定性, 尤其是范围内的数据检索
- B 树遍历需要繁琐的中序遍历, B+S 树就不需要, 直接读取单链表就可以获取范围内数据, 由于 B+tree 相比较于 B 树, 其树的高度会相对比较低, 所以在遍历时, 会少很多遍历事件, 在时间复杂度上就很低, 所以 B+ 树 是目前为止性能最高的索引结构, 性能高的影响因素是将传统的顺序遍历改为 二分查找
索引的优化
- 索引的优化实质上就是尽可能的利用到索引, 索引在查询过程中既不可能是函数的一部分, 也不能是表达式的一部分, 不然或导致索引失效的问题
- 尽可能地使用多列索引, 多列索引会让限制条件更加严格, 让索引发挥更大的作用
- 索引列的顺序有时候也影响查询效率
- 对于 Blob, text, varchar 类型的数据使用前缀索引性能最好, 可以只索引前部分的数据, 可以节省时间
- 索引覆盖
参考 :
-
https://time.geekbang.org/column/article/69236 林晓斌 -> MySQL实战45讲
-
来自公众号:腾讯技术工程 作者介绍:fanili,腾讯 WXG 后台开发工程师
-
《MySQL 技术内幕-InnoDB 存储引擎》第二版,作者:姜承尧