「MySQL高级篇」MySQL索引原理,设计原则( 三 )


索引分类在InnoDB中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表 。又因为前面我们提到的,InnoDB使用了B+树索引模型,所以数据都是存储在B+树中的 。?
每一个索引在InnoDB里面对应一棵B+树 。假设 , 我们有一个主键列为ID的表,表中有字段k,并且在k上有索引 。这个表的建表语句是:
mysql> create table T(id int primary key,k int not null,name varchar(16),index (k))engine=InnoDB;表中R1~R5的(ID,k)值分别为(100,1)、(200,2)、(300,3)、(500,5)和(600,6),两棵树的示例示意图如下:

「MySQL高级篇」MySQL索引原理,设计原则

文章插图
从图中不难看出,根据叶子节点的内容,索引类型分为主键索引和非主键索引 。
主键索引数据表的主键列使用的就是主键索引 , 且会默认创建,这也是为什么 , 我们还没学索引的时候,老师经常跟我们说根据主键查会快一点 , 原来主键本身就建好了索引 。主键索引的叶子节点存的是整行数据 。在InnoDB里,主键索引也被称为聚簇索引(clustered index) 。
辅助索引辅助索引的叶子节点内容是主键的值 。在InnoDB里,辅助索引也被称为二级索引(secondary index) 。?
如下图:
  • 主键索引存放了整行数据
  • 辅助索引只存放了自己本身 , 以及id主键用于回表查询
?
「MySQL高级篇」MySQL索引原理,设计原则

文章插图
?
根据上面的索引结构,我们来讨论一个问题:基于主键索引和辅助索引的查询有什么区别??
  • 如果语句是select * from T where ID=500,即主键查询方式 , 则只需要搜索ID这棵B+树;
  • 如果语句是select * from T where k=5,即普通索引查询方式,则需要先搜索k索引树 , 得到ID的值为500,再到ID索引树搜索一次 。这个过程称为回表 。
也就是说,基于辅助索引的查询需要多扫描一棵索引树 。因此,我们在应用中应当尽量使用主键查询 。?
除非说,我们所要查询的数据 , 刚好就是我们索引树上存在的,此时我们称之为覆盖索引--即索引列中包含了我们要查询的所有数据 。同时 , 二级索引又分为了如下几种(先简单略过即可,后续我们再慢慢了解):?
  • 唯一索引(Unique Key) :唯一索引也是一种约束 。唯一索引的属性列不能出现重复的数据 , 但是允许数据为 NULL,一张表允许创建多个唯一索引 。建立唯一索引的目的大部分时候都是为了该属性列的数据的唯一性 , 而不是为了查询效率 。
  • 普通索引(Index) :普通索引的唯一作用就是为了快速查询数据,一张表允许创建多个普通索引,并允许数据重复和 NULL 。
  • 前缀索引(Prefix) :前缀索引只适用于字符串类型的数据 。前缀索引是对文本的前几个字符创建索引,相比普通索引建立的数据更小,因为只取前几个字符 。
  • 全文索引(Full Text) :全文索引主要是为了检索大文本数据中的关键字的信息,是目前搜索引擎数据库使用的一种技术 。Mysql5.6 之前只有 MYISAM 引擎支持全文索引,5.6 之后 InnoDB 也支持了全文索引
扩展--索引下推所谓下推,顾名思义,其实是推迟我们的回表操作,MySQL不会轻而易举让我们去回表 , 因为很浪费 。什么意思呢?来看下边这个例子 。
我们建立了一个复合索引(name,status) , 索引中也是按这个字段来存储的,类似图中这样:
复合索引树(只存储索引列和主键用于回表)
namestatusid(主键)小米101小米212我们执行这样一条语句:
SELECT * FROM tb_seller WHERE name like '小米%' and status ='1' ;
  1. 首先我们在复合索引树上 , 找到了第一个以小米开头的name -- 小米1
  2. 此时我们不着急回表(回到主键索引树搜索的过程,我们称为回表),而是先在复合索引树判断status是否=1 , 此时status=0,我们直接就不回表了 , 直接继续找下一个以小米开头的name
  1. 找到第二个-- 小米2,判断status=1,则根据id=2去主键索引树上找,得到所有的数据
这种先在自身索引树上判断是否满足其他的where条件,不满足则直接pass掉,不进行回表的操作,就叫做索引下推 。
最左前缀原则所谓最左前缀,可以想象成一个爬楼梯的过程,假设我们有一个复合索引:name,status,address,那这个楼梯由低到高依次顺序是:name,status , address,最左前缀,要求我们不能出现跳跃楼梯的情况 , 否则会导致我们的索引失效:?

推荐阅读