1.什么是索引?

索引是创建在数据库表上的,索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息,是提高数据库性能的重要方式。

2.索引的作用

索引就像书籍的目录,当我们要搜索想看的内容的时候,先从目录搜索,然后找到内容的页数,再翻到相应的页去查看就可以了,比我们一页页翻着查找要快很多,所以索引的核心就是加快SQL的查询。

3.Mysql索引使用的数据结构,为什么没有使用其他数据结构?

Mysql索引的底层结构使用的是B+树,叶子结点会进行排序。

(1)链表

        链表的查询速度是O(N),每次查询都得从链表头开始查询,例如上面查询“xiaxia”,如果xiaxia在1000的位置,那么需要遍历1000次才能查找到。

(2)数组

       有人可能会说,查询速度肯定是数组最快呀,毕竟O(1),的确单纯就select的话,采用数组的形式是最合适的,但是采用数组会遇到如下几个问题:1、采用数组的话,其他操作如Delete、Update、Insert就不合适了;2、另外一个原因:索引是存在于磁盘中,当索引非常大的时候,达到几个G的时候,无法一次加载到内存中。

(3)哈希结构

  HashMap查询速度为O(1),但HashMap因为自身结构原因:乱序存储的,做等值查询速度快,但如果进行范围查询就会变得非常困难。

(4)平衡二叉树

      二叉查找树查询的时间复杂度是O(logN),查找速度最快和比较次数最少,既然性能已经如此优秀,但为什么实现索引是使用B+Tree而不是二叉查找树,关键因素是磁盘IO的次数,从二叉树的查找过程了来看,树的高度和磁盘IO的次数都是4,所以最坏的情况下磁盘IO的次数由树的高度来决定,数据量大的情况下树的高度会很高,查询时的IO次数也会非常的大。

从前面分析情况来看,减少磁盘IO的次数就必须要压缩树的高度,让瘦高的树尽量变成矮胖的树,所以B-Tree就在这样伟大的时代背景下诞生了。

(5)B树

一个m阶的B树具有如下几个特征:

1)根结点至少有两个子女。

2)每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m

3)每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m

4)所有的叶子结点都位于同一层。

5)每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划。

Mysql数据库——索引

 

虽然一个节点可以存多个值把树的高度进行了压缩,较AVL树来说查询时IO次数大大减少了(尤其是对于大数据量来说),但是查找时每次进行更深一层比对时,仍都要进行IO,而且在进行范围查找时,需要范围内的每个数值都要进行遍历,效率和代价仍达不到比较好的效果。

(6)B+树:

B+树的特征:

1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。

2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。(链表)

3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

4、B+树查找时是从上到下查找;B-树则是从下往上查找(中序遍历)

B+树的优势:

1.单一节点存储更多的元素(这样该节点下分支变多了,树变矮胖了),使得查询的IO次数更少。

2.所有查询都要查找到叶子节点,查询性能稳定。

3.所有叶子节点形成有序链表,便于范围查询。

Mysql数据库——索引

因此B+树最适合做我们MySQL数据库中索引的底层结构。

4.索引的分类

(1)普通索引:没有任何限制条件,可以给任何类型的字段创建普通索引。

(2)唯一性索引:使用UNIQUE修饰的字段,值不能够重复,主键索引就隶属于唯一性索引。

(3)主键索引:使用Primary Key修饰的字段会自动创建索引。

(4)单列索引:在一个字段上创建索引。

(5)多列索引:在表的多个字段上创建索引。

(6)全文索引:使用FULLTEXT参数可以设置全文索引,只支持CAHR,VARCHAR和TEXT类型的字段上,

常用语数据量较大的字符串类型上,可以提高查询速度;只有MyISAM存储引擎支持。

(7)空间索引:使用SPATIAL参数可以设置索引为空间索引,空间索引只能建立在空间数据类型上。Mysql中的空间数据类型包括GEOMETRY和POINT、LINESTRING和POLYGON等。

5.创建索引的方式

(1)在创建表时创建索引:

 create table table_index(id int,name varchar(10),index(id);

(2)在创建表后创建索引

create index name_index on student (name);

(3)查看索引:

explain select * from student where name = 'Tom';

Mysql数据库——索引

6.索引的设计原则

(1)给区分度高的字段创建索引

(2)给经常需要排序,分组和多表联合操作的字段创建索引

(3)给常作为查询条件的字段创建索引

(4)索引的数目不宜过多

(5)使用数据量少的索引(如前缀索引,主要针对字符串类型,字符串类型尽量创建前缀索引

(6)对于多列索引,优先指定最左边的列集

(7)删除不再使用或者很少使用的索引

7.主键索引,辅助索引,聚集索引,非聚集索引

我们主要学习一下MySQL两个重要的存储引擎,MyISAM和InnoDB存储引擎的索引结构。

(1)MyISAM存储引擎 - 主键索引

MyISAM引擎使用B+树作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM主键索引的原理图:

 

Mysql数据库——索引

(2)MyISAM存储引擎 - 辅助索引

在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复,如果给其它字段创建辅助索引,结构图如下:

 

Mysql数据库——索引

根据上面两张图,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

可以看到,MyISAM存储引擎,索引结构叶子节点存储关键字和数据地址,也就是说索引关键字和数据没有在一起存放,体现在磁盘上,就是索引在一个文件存储,数据在另一个文件存储,例如一个user表,会在磁盘上存储三个文件 user.frm(表结构文件) user.MYD(表的数据文件) user.MYI(表的索引文件)。

MyISAM的索引方式也叫做非聚集索引,之所以这么称呼是为了与InnoDB的聚集索引区分!

(3)InnoDB存储引擎 - 主键索引

InnoDB存储引擎的主键索引,叶子节点中,索引关键字和数据是在一起存放的,如图:

Mysql数据库——索引

可以看到,索引关键字和数据在叶节点上,在一起存储。

(4)InnoDB存储引擎 - 辅助索引

InnoDB的辅助索引,叶子节点上存放的是索引关键字和对应的主键,如图:

 

Mysql数据库——索引

辅助索引的B+树,先根据关键字找到对应的主键,再去主键索引树上找到对应的行记录数据。

从索引树上可以看到,InnoDB的索引关键字和数据都是在一起存放的,体现在磁盘存储上,例如创建一个user表,在磁盘上只存储两种文件,user.frm(存储表的结构),user.ibd(存储索引和数据)。

Mysql数据库——索引

 

InnoDB的索引树叶节点包含了完整的数据记录,这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。例如:聚集索引就像是查字典使用先找拼音首字母,找到之后再去查找需要找的汉字,而非聚集索引则是需要查找偏旁部首来直接确定汉字所在的页数(地址)。

 

相关文章: