索引分类
分类 | 含义 | 特点 | 关键字 |
---|---|---|---|
主键索引 | 针对于表中主键创建的索引 | 默认自动创建,只能有一个 | primary |
唯一索引 | 避免同一个表中的某个数据列中的值重复 | 可以有多个 | unique |
常规索引 | 快速定位特点数据 | 可以有多个 | / |
全文索引 | 全文索引查找的是文本中的关键字,而不是比较索引中的值 | 可以有多个 | fulltext |
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种
分类 | 含义 | 特点 |
---|---|---|
聚集索引(Clustered Index) | 将数据存储与索引放到了一块,索引结构的叶子节点保存了数据 | 必须有,而且只有一个 |
二级索引(Secondary Index) | 将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键 | 可以存在多个 |
二级索引也叫辅助索引,或叫非二级索引
由于聚集索引必须要有,所以讲一下聚集索引的选取规则,如下
1、如果存在主键,主键索引就是聚集索引(优先选这个,表中没主键才会选下面两个中的一个)
2、如果不存在主键,即使用第一个唯一(unique)索引作为聚集索引
3、如果没有主键,或没有合适的唯一索引,则InnoDB会自动生成一个rowid作为隐藏的聚集索引
聚集索引 例如某个表id为主键,拿id为5举例,5对应的就是B+tree树的索引5,这个索引5在B+Tree树的最底部的叶子节点,5对应的节点的数据 就是表里面id为5的一整行数据,比如表里面id为5的那行可能会有name,age等数据,就会跟id为5一起存放在5对应的底部节点(我们叫叶子节点)位置 总结:聚集索引的B+Tree的叶子节点的数据就是对应表中主键索引那一行的数据。注意聚集索引只有一个,即表中数据每行只有一个字段可以作为聚集索引
二级索引 例如在表的一行中,已知主键是id字段,那么聚集索引就是主键索引(即这个具体的id),该表该行中的name可以作为二级索引,二级索引也是B+Tree的结构, 注意二级索引在B+Tree结构的底部节点(我们叫叶子节点)存放的数据是对应表中该行的id值 总结:二级索引的B+Tree的叶子节点的数据就是对应表中该行主键索引的id值
思考右边这条查询的SQL语句执行过程是怎么样的,假设id是主键,select * from user where name = 'Arm';
1、根据name字段查询,走的是B+Tree结构的二级索引,找到该二级索引的B+Tree树,在根节点对比另一个名字例如Lee,因为字母A在L的前面,所以会 走根节点的左侧到达第二层,例如再跟第二层的Geek名字作对比,因为字母A在G的前面,所以会走Geek交叉节点的左侧到达第三层,如果此时刚好到最 底部的叶子结点Arm,我们就拿到了该Arm叶子节点存放的id值,例如id值为10
2、因为我们要求返回的是*,也就是这一行的所有字段,所以第一步拿到id10之后,就会拿着id为10去聚集索引的B+Tree结构中查找,首先是到达聚集索 引的根节点,在根节点对比另一个id例如id15,因为10小于15,所以会走根节点的左侧到达第二层,例如再跟第二层的id为10作比较,因为10大于等于10, 所以会走第二层10交叉点的右侧达到第三层,如果此时刚好到最底部的叶子节点10,就成功拿表中的id为10的一整行数据
3、即可查询到。注意第1步到第2步称为回表查询
回表查询:先走二级索引的B+Tree,找到主键值(不一定是id),再根据这个主键值去聚集索引的B+Tree找到这个主键值对应表中的一整行的行数据 回表查询的原理:需要扫描两个索引(二级索引和聚集索引),降低效率
索引思考题
1、以下SQL语句,哪个执行效率高?为什么?
xxxxxxxxxx
select * from user where id = 10;
select * from user where name = 'Arm';
备注:id为主键,name字段创建的有索引
答案: 第一条语句的效率高,因为第一条语句直接拿主键值id去聚集索引的B+Tree结构中查找,找到的就是id为10的一整行数据,避免了回表查询
2、InnoDB主键索引的B+Tree高度为多高呢? 思路:主键索引是聚集索引,聚集索引的叶子节点存放的是行数数据(即表的主键值的一整行数据),在B+Tree中的每一个节点都是存放在一个页中,一个也 页的大小是固定的,也就是16k,也就是一个节点能够存储的key和指针的个数是有限的,当我们要计算这个B+Tree的高度,我们可以假设如下:
一行数据大小为1k,一页中可以存储16行这样的数据。由于InnoDB的指针占用6个字节的空间,求key占用字节其实是取决于主键的类型,假设主键类型 即使为bigint,那key的占用字节数就是为8(如果主键类型是int,那么key就占4个字节)。就可以进行下面的估算:
假设树的高度为2,设key为n,由于指针永远比key多1,所以指针为n+1 n8+(n+1)6=161024, 算出n约为1170,117116=18736 即高度为2的树的高度为18736字节
假设树的高度为3 1171117116=21939856 即高度为3的树的高度为21939856字节
我们可以得出结论,即使往InnoDB结构的B+Tree中存储21939856字节(21MB)的数据,树的结构也才3层,即3次检索内必然会得出要的结果, 效率非常高,画图也简单毕竟只有3层。如果业务的数据量非常大,大于这里的3层,就要考虑分库分表(后面会学)