文章详情

短信预约信息系统项目管理师 报名、考试、查分时间动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

关于索引我能说的那些事儿

2015-01-11 23:06

关注

关于索引我能说的那些事儿

本文是自己对MySQL的InnoDB索引的理解,如有错误,还望不吝指出。

1 索引

  索引两个大字往那里一摆,刚接触不久的朋友可能对这个概念有点陌生,不好理解。没有关系,先用一个简单的例子入手,比方说现在我们要从一本字典中查一个字,那么我们可以从目录中的n字母找到这个字,发现在164页,然后翻到164页就可以看到关于这个的解释、用法等。

1581947228339

  在上面这个例子中,我们不是从第一页开始一页一页的找,而是先从目录中根据拼音开头找,找到之后翻到其对应的页数就找到了我们所需要的牛字。在这整个过程中,这个目录的字母就是我们所说的索引。我们查找数据的时候先通过这个目录找到对应记录的地址,再去这个地址找到我们所需要的数据,这个过程相比我们从头找到尾的效率要高许多,这就是索引的作用——提高性能

​  接下来所讲的内容如果没有备注则都是以InnoDB为主。

2 索引的类型

​  在MySQLInnoDB引擎中,最常见的索引就是B-Tree索引和Hash索引。

  这两种算是比较常见的索引类型,除此之外还有一种全文索引,可以实现搜索引擎类似的功能,但还没见人用过,便不加了解。

3 B+Tree的结构

​  首先先看看B+Tree是怎么出现的。

​  在一开始的时候使用的是平衡二叉树作为索引树,但是随着数据量的增大二叉树的表现有点疲软,后来便出现的一种新的结构叫作B-Tree,这种数据结构有多个子节点(不再是固定两个),而在每个节点上面都存着数据和其他节点的引用,很大程度上解决了二叉树带来的效率问题,然而时间再次推进,B-Tree的表现也逐渐下滑,此时则出现了一种新的实现方式——B+Tree

​  关于B+Tree,我们先看一个图。

1581951423270

​  如上图,我们存储的数据是1、2、3、4、5、6,所有的数据都在叶子节点中,所谓的叶子节点就是上图中最下层真正存放数据的节点,而上面那些只存了key和引用的则称之为非叶子节点。

​  这里需要注意的是,在InnoDB中,只有主键索引的叶子节点存放才是真正的数据信息,其他列的索引在叶子节点中存放的数据信息是主键的值,也就是说如果我们使用的是普通的索引,那么其查找的过程为:

​ 在使用的索引树(有多少个索引就有多少棵树)中进行查找,找到了对应的叶子节点之后拿到其储存的主键值,再去主键索引树中查找对应主键的叶子节点的数据信息,而一般把通过主键去磁盘中读取数据的操作叫做"回"。

​  主键索引和普通索引可以结合下图理解

1582011585220

​  这就是InnoDBB+Tree的实现方式,跟普通的B-Tree相比有了稳定的性能,并且在范围查询(比方说id<10)方面表现的更加优异。如上所说,B-Tree的结构直接把数据的信息放在节点中,没有是否叶子节点之分,查到之后就立马返回,如下:1582012558215

4 聚簇索引和非聚簇索引

​  聚簇索引并非一种索引类型而是一种储存方式,表示索引的键值对和临近的数据行储存在一起,在物理的储存顺序是有序的,在InooDB中,主键索引就是聚簇索引的实现

​  由于数据行只有一颗索引树有存,所以也就只有一个聚簇索引,也就是说除了主键索引是聚簇索引之外,其他列的索引都是非聚簇索引。而聚簇索引的储存特性也就决定了我们在查到范围数据比如limit 10这种操作的时候能够进行顺序IO而非随机IO从而提升了查找的效率。

​  当然有优必有劣,聚簇索引的储存方式也就决定了主键只有在递增的时候发挥得比较好,主键是递增的,每次插入时往上次插入位置的下一个位置插入就行(因为新增的主键一定比之前的大),如果页满了就插入下一页,但是如果主键是不规则的,譬如UUID来做主键,由于其每次插入的主键不一定比之前的大,那么则要进行比较从而进行数据的移动需要花费的时间和空间要更多一些,并且如果插入一个饱满的页中就会引发列分裂从而造成空间碎片

5 复合索引和覆盖索引

​  首先我们得知道这两个不是同一个概念。

  另外,使用覆盖索引可以实现延迟关联,从而提升查询的效率(前提是使用覆盖索引过滤的数据足够多),比方说现在有一个SQL:

select * from user_info where user_number = '123' and user_name like '%三%';

  在user_info表中有复合索引(user_number, user_name),上面的写法的执行过程为:

  1. 从索引树中找到user_number="123"的所有主键(user_name为全模糊,不会用到索引),注意这里还没执行user_name like "%三%"的操作。
  2. 根据这些主键从主键索引中找到对应的数据行,将这些数据行从磁盘加载到内存中
  3. 加载完成之后,从这些数据行中筛选出user_name like "%三%"的数据,将这些数据返回

  这是正常的执行过程,但是我们可以改写这个SQL,让其变成使用覆盖索引的形式:

SELECT
  *
FROM
  user_info
INNER JOIN (
  SELECT
      id
  FROM
      user_info
  WHERE
      user_number = '123'
  AND user_name LIKE '%三%'
) t ON user_info.id = t.id;

  这样临时表t则是使用覆盖索引生成的记录,是在内存操作,注意由于索引的叶子节点存储的是主键值,所以使用主键值的话也能用到覆盖索引

  这个写法跟上面不同的地方在于,由于使用了覆盖索引,所以对于user_numberuser_name的条件过滤都是在内存中进行的,在内存过滤完成之后将拿到的主键值再去主键索引取数据行。跟第一种写法的效率区别则是在于覆盖索引能够过滤多少条数据

  拿这两个SQL举个例子,假设在user_info表中user_number="123"的数据有10W条,user_name中包含"三"的数据有200条,那么如果是第一种写法,则有:

从索引中拿到10Wuser_number="123"的主键值到主键索引中拿到10W条数据行然后加载到内存中,再从内存中的10W条数据中找出user_name包含"三"200条数据。

  而如果是第二种写法,则变成了:

先在索引中找到user_number="123"的节点,然后再从这些节点中找出user_name包含"三"200个主键值,注意到目前为止都是内存操作还没进行IO,然后根据这200个主键值从磁盘加载200条数据数据行到内存中返回。

  对比可以清楚的看到,第一种写法进行了10W数据的IO再过滤,而使用覆盖索引的方式则只进行200条数据的IO,性能的提升肯定是非常大的,这种使用覆盖索引来提升性能的方式就叫做"延迟关联"。当然,性能的提升决定于覆盖索引能够过滤的数据行数,如果上面的例子中user_name包含"三"的记录有9W条,那么此时"延迟关联"的写法提升就没那么明显了。

6 Extra中的一些信息

​  最后讲下MySQLexplainExtrausing whereusing indexusing index condition

  此时由于age不是前导列,但为复合索引的其中一列,并且查询的是所有列,并不会用到覆盖索引,所以是index condition;using where而不是或者using index,其中using where是因为 sex = 1这个条件,如果没有的话则只有using index condition
  注意:using index condition索引非前导列的条件(比方说上方的age)时,这部分的条件筛选是在内存中进行,而不是回表返回数据行之后再执行这个过滤条件。如上方的sql中,其顺序就是先找到user_id = 1的索引记录,然后在这些记录中过滤出age = 1的记录,到这里都是内存操作再通过回表返回的数据行中过滤sex = 1的数据,所以using index condition的过滤时间是发生在回表之前
  
  
  
  
  
  

参考:《高性能MySQL》第三版

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯