0
点赞
收藏
分享

微信扫一扫

《MySQL——索引笔记》


目录

  • ​​回表​​
  • ​​覆盖索引​​
  • ​​最左前缀原则​​
  • ​​联合索引的时候,如何安排索引内的字段顺序?​​
  • ​​索引下推​​
  • ​​重建索引问题​​
  • ​​联合主键索引和 InnoDB 索引组织表问题​​
  • ​​in与between的区别​​


回表

回到主键索引树搜索的过程,我们称为回表。

覆盖索引

覆盖索引就是在这次的查询中,所要的数据已经在这棵索引树的叶子结点上了。

select ID from T where k between 3 and 5

《MySQL——索引笔记》_mysql
ID 的值已经在 k 索引树上了,因此可以直接提供查询结果,不需要回表.
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。

覆盖索引的第二个使用:在联合索引上使用,也可以避免回表。
如果现在有一个高频请求,要根据市民的身份证号查询他的姓名。我们可以建立一个(身份证号、姓名)的联合索引。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。

最左前缀原则

联合索引先根据第一个字段排序,如果第一个字段有相同的,就按照第二个字段排序。
《MySQL——索引笔记》_联合索引_02
只要满足最左前缀,就可以利用索引来加速检索。这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。

联合索引的时候,如何安排索引内的字段顺序?

第一原则:
如果通过调整顺序,可以少维护一个索引,那么这个顺序往往就是需要优先考虑采用的。
如果我们有个频繁的要求:根据姓名找到该人身份证,那么应该建立联合索引:(name,ID)
反之,如果我们有个频繁的要求:根据该人身份证找到该人姓名,那么应该建立联合索引:(ID,name)

索引下推

索引覆盖是你要查的信息在二级索引中已经有了,就不需要回表。索引下推是你的过滤条件有一部分符合了最左前缀,那么会用上索引,如果此时不符合最左前缀的部分刚好有联合索引中的字段,那么在利用最左前缀进行索引查询的同时,会根据这些字段多做一步过滤,减少索引查询出来的条数,这样就减少了回表次数。
如:

mysql> select * from tuser where name like '张%' and age=10 and ismale=1;

《MySQL——索引笔记》_mysql_031 每次都需要回表


《MySQL——索引笔记》_字段_042 下推,先滤除不符合的,再回表


重建索引问题

假设,我们有一个主键列为 ID 的表,表中有字段 k,并且在 k 上有索引。

mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;

如果你要重建索引 k:

alter table T drop index k;
alter table T add index(k);

如果你要重建主键索引:

alter table T drop primary key;
alter table T add primary key(id);

上面这两个重建索引的作法对此有什么理解?
为什么要重建索引?
索引可能因为删除,或者页分裂等原因,导致数据页有空洞,重建索引的过程会创建一个新的索引,把数据按顺序插入,这样页面的利用率最高,也就是索引更紧凑、更省空间。
理解
不论是删除主键还是创建主键,都会将整个表重建。所以连着执行这两个语句的话,第一个语句就白做了。
推荐使用:

alter table T engine=InnoDB

联合主键索引和 InnoDB 索引组织表问题

有这么一个表:

CREATE TABLE `geek` (
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
`d` int(11) NOT NULL,
PRIMARY KEY (`a`,`b`),
KEY `c` (`c`),
KEY `ca` (`c`,`a`),
KEY `cb` (`c`,`b`)
) ENGINE=InnoDB;

既然主键包含了 a、b 这两个字段,那意味着单独在字段 c 上创建一个索引,就已经包含了三个字段了呀,为什么要创建“ca”“cb”这两个索引?同事告诉他,是因为他们的业务里面有这样的两种语句:

select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;

为了这两个查询模式,这两个索引是否都是必须的?为什么呢?
表记录:
主键 a,b 的聚簇索引组织顺序相当于 order by a,b ,也就是先按 a 排序,再按 b 排序,c 无序。

a

b

c

d

1

2

3

d

1

3

2

d

1

4

3

d

2

1

3

d

2

2

2

d

2

3

4

d

索引 ca 的组织是先按 c 排序,再按 a 排序,同时记录主键:
这个跟索引 c 的数据是一模一样的。

c

a

b

2

1

3

2

2

2

3

1

2

3

1

4

3

2

1

4

2

3

索引 cb 的组织是先按 c 排序,再按 b 排序,同时记录主键:

c

b

a

2

2

2

2

3

1

3

1

2

3

2

1

3

4

1

4

3

2

所以,结论是 ca 可以去掉,cb 需要保留。

in与between的区别

--1.
select * from T where k in(1,2,3,4,5)
--2.
select * from T where k between 1 and 5

1.in 内部的数字是未知的,不知道是否有序,是否连续等,所以你只能一个一个去看。
2.一个已知的升序、范围查询,只需定位第一个值,后面遍历就行了。


举报

相关推荐

0 条评论