likes
comments
collection
share

mysql 索引浅析

作者站长头像
站长
· 阅读数 13

索引在我们日常开发过程中可以起到加速检索的效果,很多时候索引可以作为一个数据库查询的优化手段。下面我们来探析一下mysql的索引的基础相关知识

索引(Index)是帮助MySQL高效获取数据的数据结构,索引是一种数据结构。

可以将索引看做一本书的目录来理解,没有索引的情况下,我们检索数据需要直接从头检索所有数据,有了索引之后就像书籍有了目录,我们可以直接跳到对应 '页结构' 来直接进行查询。

如何使用一个索引呢

CREATE TALBE 表名 ( 各种列的信息 ··· , 
[INDEX] 索引名 (需要被索引的单个列或多个列) )

下面举一个索引的例子:

CREATE TABLE demo( uuid INT, age INT, name CHAR(255), PRIMARY KEY(uuid), INDEX idx_name_age (name, age) );

mysql索引的种类和特点

mysql中用的比较多的索引主要是INNODB和MyISAM。

  1. INNODB表索引的指索引中键值与表数据存储在一起,这里的索引与数据存在一起,因此存储效率更高一些。
  2. MyISAM表索引与表数据是分开存储的,索引保存在"表名.MYI"文件内,而数据保存在"表名.MYD"文件内,因此我们查到索引之后还需要再次回表,才能查询到相关数据。MyISAM和INNODB的二级索引有点类似。

按照索引的性质来进行划分,可以分为:

主键索引:给表设置主键,这个表就拥有主键索引。

唯一索引:unique

普通索引:增加某个字段的索引,比如用户表根据用户名查询。

组合索引:使用多个字段创建索引,遵循最左原则,比如创建索引(col1 + col2 + col3),相当于创建了(col1)、(col1,col2)、(col,col2,col3)三个索引。

mysql索引原理

mysql 索引浅析 MySQL数据库索引采用的是B+Tree结构,在B-Tree结构上做了优化改造。 B-Tree结构:

  • 索引值和data数据分布在整棵树结构中
  • 每个节点可以存放多个索引值及对应的data数据
  • 树节点中的多个索引值从左到右升序排列

可以通过在B+树上面进行二分查找,而非完整遍历,同时又因为B+树节点很多,非常适合存储数据。例如B+树一层有100个节点,如果有2层那么可以存储100100,如果有四层可以存储1000010000的数据了,可以在尽量小的增加检索压力的情况下,尽可能增加数据检索性能。

mysql索引适用场景

索引虽然很好但是底层使用B+树作为数据结构,因此需要付出额外的时间和空间成本。 空间上面来说:每建立一个索引都要建立很多个数据页,而每个数据页的大小是16KB。 时间上面来说:每次对表中的数据进行增、删、改操作时,都需要去修改各个B+树索引。B+树每层节点都是按照索引列的值从小到大的顺序排序而组成了双向链表。不论是叶子节点中的记录,还是内节点中的记录(也就是不论是用户记录还是目录项记录)都是按照索引列的值从小到大的顺序而形成了一个单向链表。而增、删、改操作可能会对节点和记录的排序造成破坏,所以存储引擎需要额外的时间进行一些记录移位,页面分裂、页面回收什么的操作来维护好节点和记录的排序。

我们使用索引相关的适用场景如下:

1.全值匹配

如果我们的搜索条件中的列和索引列一致的话,这就是全值匹配。例如:

SELECT * FROM demo WHERE name = 'Aax' AND age = 18 ;

在这条查询语句中,B+树的记录按照name的顺序进行排列,然后按照age的顺序进行排列。因此会首先检索到Aax的这个人,接着检索age=18的人。我们建立索引的两个列都被用到了。

2.匹配条件最左面的列

当然我们也可以并不需要将联合索引的所有内容都放到查询条件。

SELECT * FROM demo WHERE name = 'Aax'  ;

只要包含左边的列,都可以使用索引带来的加速查询效果。

3.范围值

B+树中,所有记录都是按照索引列的值从小到大的顺序排好序的,所以这极大的方便我们查找索引列的值在某个范围内的记录。

SELECT * FROM demo WHERE name > 'Asx' AND name < 'Bob';

由于B+树的索引,因此上面查询是按照如下顺序进行的:

  1. 查询name='Asx'的记录
  2. 查询name='Bob'的记录
  3. 查询两者之间的记录 由于所有记录彼此之间通过链表链接,因此取得他们之间的数据,只需要遍历链表即可。

4.分组

有时候我们为了方便统计表中的一些信息,会把表中的记录按照某些列进行分组。例如

SELECT name ,age,FROM demo group by name,age ;

这个过程需要两步:

  1. 对数据按照 name进行分组
  2. 对以及按照name分组好的数据按照age进行分组 如果没有索引,我们需要重新运行,但是有了索引可以直接利用索引数据,取得相关结果。

5.排序

我们查询数据的时候可能会进行排序,但是如果数据量过大,内存无法承受,需要逐步读取采用外部排序的方式进行。一旦外部排序,消耗时间可能会比较长。但是可以用索引来加快排序。

例如我们将所有数据按照name进行排序,name相等的话按照年龄进行排序。

SELECT * FROM demo order by name,age ;

因为和我们建立的索引一致,因此我们可以直接从索引中取得相关数据,不再需要进行排序。

参考文献

mysql索引原理

从根上理解mysql

Mysql索引:图文并茂,深入探究索引的原理和使用