组合索引
一句话解释:由两个或者以上的列组成的索引即为组合索引。
细说:
普通索引或者聚簇索引都是一个列成为一个索引B+Tree,联合索引是多个列组成的索引B+Tree,普通索引的B+Tree的叶子节点存储的是索引值和主键值,但是联合索引的叶子节点存储的是多个列组成的键值对。
例如:
数据表:
| id | user_id | age |
|---|---|---|
| 5 | 1 | 2 |
| 6 | 1 | 3 |
| 7 | 3 | 4 |
create table tss_biz_parcel.user
(
id int null,
user_id int null,
age int null
);
create index union_index
on tss_biz_parcel.user (user_id, age);
以上数据表中设置user_id和age为组合索引,并设置三条数据。
那么组合索引的B+Tree结构如下(举例子这样画,真实的B+Tree需要区分分界点):
组合索引的列通过键值对顺序的方式组成叶子节点的数据。因此select * from user where user_id = 1 and age = 2;时会走组合索引然后定位到主键5,然后再通过聚簇索引B+Tree查询行数据。
使用该组合索引的好处在于组合索引的数据是有序的,例如select * from user where user_id = 1;该语句会走索引并且查询出来的数据也是对age进行排序的。无需再进行排序操作。
组合索引还涉及到另一个问题,最左匹配原则。一句话概括:使用组合索引时只能按照顺序从第一个向后排序使用索引才会执行组合索引。select user_id,age from user where age = 2;select user_id,age from user where age = 2 and user_id = 1;以上两个语句不会执行组合索引,因为没有按照user_id和age的顺序作为查询条件。
覆盖索引
一句话解释:从辅助索引中就可以查询到的记录。
细说:
从组合索引的例子中select * from user where user_id = 1 and age = 2;会遍历两个B+Tree,一个是组合索引的B+Tree,一个主键索引的B+Tree,那么有没有什么方式可以只走一个索引B+Tree就可以直接查询到数据呢?
答案就是覆盖索引,如果我们修改SQL语句为select user_id,age from user where user_id = 1 and age =2;那么该查询执行一次组合索引B+Tree就可以得到结果数据。主要的问题在于查询的记录可以直接从联合索引B+Tree中获取到,不需要再遍历主键B+Tree。
这就是覆盖索引的好处当不需要查询整个行记录数据时,可以通过覆盖索引的方式得到查询结果,大大减少IO的次数。
这也是避免平时使用select * 的原因。
引用
- MySQL技术内幕