从根上彻底理解MySQL的索引( 四 )

  • 数据页中存放的用户记录和目录项记录由原本的按照主键排序变为按照name列排序,如果name列相同,那就按照phone列排序;(如果phone列再一样呢?你现在明白为什么要存储主键值了吗?)
  • 再画个图吧(有点偷懒了哈,数据页号没换):
    从根上彻底理解MySQL的索引

    文章插图
     
    还是和二级索引一样,利用B+树快速定位到数据页,然后页内快速定位到记录,找到记录中的主键id,再回表,如果找到多条符合条件的记录,就多回几次表 。
    4. InnoDB其他的索引方式以上介绍的是B+树索引,它其实是InnoDB存储引擎提供的众多索引中的一种而已,但却是使用最多、面试中最常被问到的一种索引 。除此之外,还提供了其他的索引方式,例如我的TablePlus工具(mac上的MySQL连接工具)提供了4种 。
    从根上彻底理解MySQL的索引

    文章插图
     
    4.1 HASH如果你用过JAVA的HashMap或者Python的字典,你对这个概念就应该很清楚了 。
    哈希表是一种采用键值对(Key-Value)存储数据的结构,它会根据索引字段生成哈希码和指针,指针指向表中的数据 。不可避免地,多个索引字段值经过哈希函数的换算,会出现同一个值的情况,处理这种情况的一种方法就是创建一个单向链表 。如下图所示,我们为name字段创建HASH索引:
    从根上彻底理解MySQL的索引

    文章插图
     
    哈希索引有3个重要特点:
    1. 查询速度非常非常快,时间复杂度是O(1),因为哈希索引中的数据不是按照顺序存储的,所以不能用于排序;
    2. 查询数据的时候要根据键值计算哈希码,所以它只能支持等值查询(=、IN),不支持范围查询(>、<、>=、<=、BETWEEN、AND);
    3. 如果哈希冲突,就得采用添加单向链表的方法解决,会造成效率下降 。
    另外,虽然提供了HASH的索引方法,但是在InnoDB中无法显式创建一个HASH索引,所谓地支持哈希索引其实指的是自适应哈希索引(AHI),是InnoDB自动为BufferPool中的热点页创建的索引 。虽然TablePlus在创建索引的时候能够选择HASH,但是实际创建完之后显示类型仍然是BTREE 。
    4.2 FULLTEXT如果你的数据表有一个大文本字段,你想查询这个字段中包含「蝉沐风」的所有记录,你可能会采用LIKE '%蝉沐风%'的方式进行查询,但是索引的最左匹配原则告诉你这样的查询效率太低了,这时候全文索引就出现了 。
    为了说明问题,我们假设一个文本字段存储了这样一段文字:
    我叫蝉沐风,欢迎大家关注我的微信公众号想要快速根据某个词进行查询,首先要对这段文本进行分词,得到下列分词结果:
    我/叫/蝉/沐/风/,/欢迎/大家/关注/我/的/微信/公众号然后建立每个分词和用户记录(在搜索领域中的专业术语叫做文档)的对应关系,生成一个单词文档矩阵
    从根上彻底理解MySQL的索引

    文章插图
     
    然后就可以根据某个单词进行查询了,这也是现代搜索引擎的基本原理,感兴趣的话可以搜索一下倒排索引,再感兴趣可以了解一下Elastic Search 。
    4.3 SPATIAL是对空间数据的索引,我没使用过,就暂时解释这么多了 。
    5. MyISAM的索引方案
    从根上彻底理解MySQL的索引

    文章插图
     
    不同的存储引擎存放数据的方式不一样,产生的文件数量和格式也不一样,InnoDB文件包含2个,MEMORY文件包含1个,MyISAM文件包含3个 。我们接下来关注的就是MyISAM中的文件 。
    • .MYD文件,D代表Data,是MyISAM的数据文件,存放用户记录,也就是我们插入的表数据;
    • .MYI文件,I代表Index,是MyISAM的索引文件 。一个索引就会有一棵B+树,所有的B+树都保存在这个文件当中 。
    也就是说,不同于InnoDB的“索引即数据”的思想,MyISAM存储引擎中的索引和数据是分开存储的 。
    MyISAM中的B+树长啥样子呢?其实样子和InnoDB差不多,区别就是MyISAM的B+树的叶子节点存储的是用户记录对应的磁盘地址,所以从索引文件.MYI中找到对应的索引键(建立索引的列的值)后,会到.MYD中找到对应的用户记录 。以主键为例我再再再画个图:
    从根上彻底理解MySQL的索引

    文章插图


    推荐阅读