Mysql索引
为什么要使用索引
- 很明显使用索引的原因就是为了检索数据的时间大大减少
- 使用唯一性索引能保证数据的唯一性
索引为什么能提高查询速度
这我们得先从Mysql的数据结构看:
Mysql的数据都是存储在一种叫页的数据结构中:
当有新纪录插入时,会发生如下的过程变化:
需要知道的是
- 每个数据页之间会形成双向链表
- 单个数据页之间的记录会形成单向链表
因此,如果有这么一条SQL语句select * from user where indexname = ‘xxx’,没有任何处理,查询数据过程是这样的。
- 通过双向链表查询到记录所在的页
- 再通过页的单向链表查询到记录
很明显,时间复杂度是O(n),并不能满足基本的查找速率。
引入索引之后会是什么情况呢?
首先索引是什么呢?落实到具体代码上,可以看做是一种数据结构,它是需要额外的存储空间,目前大部分数据库会采用B+树作为索引结构,那么B+树是什么呢?这里简单说一下:
- 二叉查找树
首先要知道什么是二叉查找树–
二叉查找是基于二分法的策略提高数据的查找速度的二叉树的数据结构:
它的特点就是:
- 非叶子节点最多拥有两个子节点;
- 非叶子节值大于左边子节点、小于右边子节点;
平衡二叉树的时间复杂福维持在 O(logN)
- B树(B-树) (待完善)
下面来具体介绍一下B-树(Balance Tree),一个m阶的B树具有如下几个特征:
- 根结点至少有两个子女。
- 每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m
- 每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m
以上如果暂时不理解没关系,直接看图上具体的例子:
以(2,6)节点为例,它有三个孩子1、(3,5)、8,其中1小于2,(3,5)在2、6之间,8大于6符合我们所说的特征。
如果进行查找要怎么进行呢?
假如我们要找的是5
相信现在大致会对B树有个宏观上的了解,其实它本质上和二叉查找树是一样的,无非就是把无序的数据按照一定的规则变成相对有序的,可以缩短查询时间。
那么为什么还要引入B-树呢?有一个很现实的原因:磁盘IO时间。
要知道,索引文件是存在磁盘上的,而往往索引占用的大小可能是几个G甚至更多,所以在利用索引查询的时候,我们显然不可能把全部索引加载到内存,只能是逐一加载磁盘页。
举个例子,如果说通过二叉查找查找1需要经历五个节点,那就意味着需要5次磁盘IO,显而易见,查找经历节点的个数最多等于树的高度。
我们再对比下B树和二叉查找树结构,就会发现B树的高度远小于二叉查找树的,因此使用B树查找花费的磁盘IO时间肯定是更少的。
- B+树 (待完善)
B+树实际上就是B-树的一种变种,它拥有B树的全部特性。
前文提到过目前数据库使用的索引结构大都是B+树,至于原因肯定也猜的出来,比起B树,B+树拥有更高的查询性能。
因此B+树的索引,数据结构会是这样的:
要找到id为8的记录简要步骤:
显然,通过索引我们能快速的定位到目标页上。
为什么不把全部列都加上索引呢
- 索引的创建和维护都是需要时间的,并且这个时间会随着数据量的增加而不断变多
- 索引也会占用物理空间
索引的使用
最左前缀原则
MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city)o而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下:
select * from user where name=xx and city=xx ; //可以命中索引
select * from user where name=xx ; // 可以命中索引
select * from user where city=xx; // 无法命中索引
由于最左前缀原则,在建立联合索引的时候应当考虑字段值去重后的个数,越多的越应当放在前面。