本文我们主要从以下几个方面来简单了解MySQL中的索引.
目录
1.什么是索引?
索引(index):相当于是书的目录,我们可以通过目录来快速找到我们想找到书中某部分的内容,那么同样的,数据库中的索引也是为了帮助我们可以快速的查询(定位),检索数据库中的数据.
比如: 我们有一张学生表,如果此时我们想查询学生id为10的学生信息,没有索引的话,此时的查找过程就相当于是一个"顺序表查找"(遍历顺序表).
如果是针对顺序表查找,顺序表是在内存中,访问内存的速度比磁盘要快,并且内存中数据对比磁盘也没有那么多,其实这样的话速度也还行.
但如果是针对数据库顺序查找的话,数据库的数据是存储在磁盘上的,磁盘访问的速度会慢很多,并且存储的数据量可能也会非常的多,这个速度的话就会很慢了.
概念:索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现.
2.为什么使用索引?
类比书的目录:合理的使用索引,可以加快数据库的查询效率,提高程序的性能.
有了索引之后,对于查找的效率提升是非常巨大的,当MySQL里面的数据量达到千万级的时候(一个表里有几千万,上亿的数据)再去遍历表的话,就会非常非常低效.
MySQL在进行比较的时候并不是像我们代码里常见的for循环比较,for循环比较是纯在内存中进行比较,而MySQL的比较是在硬盘上的,硬盘的IO速度是要比内存慢好几个数量级的.
3.索引的应用场景
主要是应用在查找很频繁,但是插入,删除不频繁的场景中.
索引可以提高查找的效率,但同时也会付出一些代价.
书的目录也是需要费纸的,当然数据库的索引也是需要消耗一定的额外存储空间的,数据量越大,索引消耗的额外空间就越多.
书的目录如果确定了,后续每次对书的内容进行调整都可能会影响到目录的准确性,所以就需要调整目录.那么数据库索引也是一样,当对数据库中数据进行增删改的时候,往往也需要同步的调整索引的结构.如过频繁的对数据进行增删改的话效率也会比较低.
4.索引背后的数据结构
首先可以考虑的数据结构:
1.二叉树(二叉搜索树),如果比较平衡的话,效率会达到O(logN).
2.哈希表.查找的效率为O(N).
但是使用哈希表会存在一些问题,比如 我们要查找一个范围的数据(id>3并且id<6的学生信息).使用哈希表的话是很快可以查到id为3或者为6的学生信息的,但是我们需要的是满足条件的所有学生信息,此时使用哈希表的话难以满足.
那么我们可以考虑使用二叉搜索树(二叉搜索书的中序遍历结果是有序的),同样的我们查找id>3并且id<6的学生信息,先找到id为3的元素再找到id为6的元素,中序遍历中3和6之间的值就是想得到的结果.
相比于哈希表,二叉搜索树虽然可以处理范围查找,但是处理效率不高.
第一点:二叉搜索树的每个节点最多有两个叉,当数据量比较大的时候,树的高度就会比较高,高度对应着比较次数(对于数据库来说,每次比较就意味着磁盘IO)所以操作的效率也会比较低.
第二点:二叉搜索树的中序遍历也不是很高效,时间复杂度为O(N).
其实,真实的索引结构是一种N叉搜索树(B+树)!
在了解B+树之前,我们先了解一下B树(也写作B-树)
B树的每个节点上,都会存储N个key值,N个key值就划分除了N+1个区间,每个区间都对应到一个子树.
在B树中查找元素,过程和二叉搜索树非常相似:先从根节点出发,根据待比较的元素确定一个区间,最终在区间内找到元素值.
这里在确定区间的时候,也会进行多次比较.那么这里比较多次和二叉搜索树相比,优势体现在哪呢?
二叉搜索树中每个节点都要比较一次,比较的次数和高度相关.B树中,高度比较低,但每个节点的比较次数多了.(其实,相比于比较次数来说,磁盘IO次数是更关键的,而搜索是以节点为单位进行磁盘IO的)
所以B树的IO次数相比二叉搜索树要更少.
了解B树之后再来看看B+树.
与B树不同的是,每个节点如果有N个key值,就把他分成N个区间(子树),而且父节点的值会在子节点中体现出来,非叶子节点中的每个值也最终都会在叶子节点中体现出来.叶子节点使用链表顺序连接.
表中每行数据只在叶子节点上保存,非叶子节点只保存辅助查找的边界信息(用来定位叶子节点).
B+树的优点:
1.所有的数据都是存放到叶子节点上,只把叶子节点放到磁盘中,非叶子节点(辅助查询)可以放到内存中,这样查找的效率就更高了(减少了IO次数).
2.所有的查询最后都会落到叶子节点上,每次查询的IO次数都是差不多的,查询速度比较稳定.
3.叶子节点用链表链接之后非常适合进行范围查找,不需要再对树进行中序遍历.
5.总结
本文只限于帮助大家简单了解索引这个概念,关于索引还有许多内容需要继续总结!