提示:文章先作为初版,等后续时间充足后,补充更深的内容
索引的基本原理
一、为什么要有索引
一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是重中之重。说起加速查询,就不得不提到索引了。
二、什么是索引
索引在MySQL中也叫是一种"键”。是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。
索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。
三、索引的原理
索引的目的在于提高查询效率,与我们查阅图书所用的目录是一个道理:先定位到章,然后定位到该章下的一个小节,然后找到页数。相似的例子还有:查字典,查火车车次,飞机航班等
本质都是**:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件**,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。
数据库也是一样,但显然要复杂的多,因为不仅面临着等值查询,还有范围查询(>、<、between、in)、模糊查询(like)、并集查询or)等等。数据库应该选择怎么样的方式来应对所有的问题呢?我们回想字典的例子,能不能把数据分成段,然后分段查询呢?最简单的如果1000条数据,1到100分成第一段,101到200分成第二段,201到300分成第三段…这样查第250条数据,只要找第三段就可以了,一下子去除了90%的无效数据。但如果是1千万的记录呢,分成几段比较好?按照搜索树的模型,其平均复杂度是IgN,具有不错的查询性能。但这里我们忽略了一个关键的问题,复杂度模型是基于每次相同的操作成本来考虑的。而数据库实现比较复杂,一方面数据是保存在磁盘上的,另外一方面为了提高性能,每次又可以把部分数据读入内存来计算,因为我们知道访问磁盘的成本大概是访问内存的十万倍左右,所以简单的搜索树难以满足复杂的应用场景。
四、索引的数据结构
【使用特殊的数据结构分块/页将重要信息读取到内存中】
MySQL主要用到两种结构:B+Tree索引和Hash索引lnodb存储引擎默认是B+Tree索引
Memory存储引擎默认Hash索引;
MySQL中,只有Memory(Memory表只存在内存中,断电会消失,适用于临时表)存储引擎显示支持Hash索引,是Memory表的默认索引类型,尽管Memory表也可以使用B+Tree索引。Hash索引把数据以hash形式组织起来,因此当查找某一条记录的时候,速度非常快。但是因为hash结构,每个键只对应一个值,而且是散列的方式分布。所以它并不支持范围查找和排序等功能。
B+Tree是mysql使用最频繁的一个索引数据结构,是InnoDB和MyISAM存储引擎模式的索引类型。相对Hash索引,B+Tree在查找单条记录的速度比不上Hash索引,但是因为更适合排序等操作,所以它更受欢迎。毕竟不可能只对数据库进行单条记录的操作。
对比:
hash类型的索引:查询单条快,范围查询慢
btree类型的索引: b+树,层数越多,数据量指数级增长(我们就用它,因为innodb默认支持它),虽然查得慢但是适用于范围查询
五、B+树在实现索引上的优势以及过程。
B+树出现可以说是解决了B树的范围查找效率慢的问题。B树里面是每个节点都存储数据,而B+树的数据是存储在叶子节点
优势:
1.磁盘读写的代价更低
B树的数据和索引都在同一个节点上,那么每个块中包含的索引是少量的,如果想要去除比较深层的数据,意味着要读取更多的块,才能得到想要的索引和数据,那么就增加了IO次数
而B+树中每个块能存储的索引是B树的很多倍,那么获取比较深层的数据,也只需要读取少量的块就可以,那么久减少了磁盘的IO次数
2.随机IO的次数更少
随机I/O是指读写操作时间连续,但访问地址不连续,时长约为10ms
顺序I/O是指读取和写入操作基于逻辑块逐个连续访问来自相邻地址的数据,时长约为0.1ms
在相同情况下,B树要进行更多的随机IO,而B+树要进行更多的顺序IO,因此B+树效率也更加快
3.查询速度更稳定
由于B+树非叶子节点不存储数据,因此所有的数据都要查询至叶子节点,而叶子节点的高度都是相同的,因此所有数据的查询速度都是一样的