首页 > 图灵资讯 > java面试题>正文

金三银四精选java面试题-使用Order By时能否通过索引排序?

2024-01-10 09:59:16

 

使用Order By时能否通过索引排序?

 

我们知道在很多场景下会导致索引失效,比如说没有遵循B+树的最左匹配原则,但是也有一些情况是遵循了最左匹配原则但是还是没有走索引,这里我们使用order by进行排序的时候就有不走索引的情况,那么带大家来分析一下

 

drop table if exists `user`;
drop table if exists `user_example`;
create table `user`(
    `id` int primary key comment '主键ID',
    `card_id` int comment '身份证',
    `nickname` varchar(10) comment '昵称',
    `age` int not null comment '年龄',
    key  `card_id` (`card_id`)
) engine=InnoDB default charset=utf8mb4;

// 这里我们明明对card_id建好了单列索引,那为什么不走索引呢?
select * from `user` order by card_id

 

  • 如果索引覆盖是可以走索引的
  • 如果带上索引条件是可以走索引的

 

通过索引排序内部流程是什么呢?

 

explain select nickname,card_id,age from user order by card_id;

 

我们在了解MySQL底层是怎么排序的之前,我们先来了解一下一个概念 sort buffer .

 

首先mysql会为每一个线程都分配一个固定大小的sort buffer 用于排序。它是一个具有逻辑概念的内存区域,我们可以通过sort_buffer_size参数来控制,默认值是256kb

 

// 输入查看最,小可以设置为 32K,最大可以设置为 4G。
show variables like 'sort_buffer_size';

 

由于sort buffer 大小是一个固定的,但是我们待排序的数据量它不是,所以根据它们之间的一个差值呢,就分为了内部排序和外部排序

 

  • 待排序的数据量小于等于sort buffer 时,那我们的sort buffer就能够容纳,MySQL就可以直接在内存里面排序就行了,内部排序使用的排序算法是快排
  • 待排序的数据量大于sort buffer 时,那我们的sort buffer 就不够用了对吧。这个时候MySQL就得要借助外部文件来进行排序了。将待排序数据拆成多个小文件,对各个小文件进行排序,最后再汇总成一个有序的文件,外部排序使用的算法时归并排序

 

我们来聊聊row_id排序

 

和大家说一个这个参数max_length_for_sort_data ,在我们MySQL中专门控制用户排序的行数据长度参数。默认是4096,也就是说如果超过了这个长度MySQL就会自动升级成row_id算法。

 

// 默认max_length_for_sort_data的大小为4096字节
show variables like 'max_length_for_sort_data';

 

row_id排序的思想就是把不需要的数据不放到sort_buffer中,让sort_buffer中只存放需要排序的字段。

 

举个例子:

 

explain select nickname,card_id,age from user order by card_id;

 

我们前面说到了sort buffer,在sort buffer里面进行排序的数据是我们select的全部字段,所以当我们查询的字段越多,那么sort buffer能容纳的数据量也就越小。而通过row_id排序就只会存放row_id 字段和排序相关的字段。其余的字段等排序完成之后通过主键ID进行回表拿。

 

group by 分组和 order by 在索引使用上有什么不同吗?

 

没什么太大的差异group by实际是先进行排序,再进行分组。所以遵循order by的索引机制。


 
上一篇 金三银四精选java面试题-什么是联合索引,组合索引,复合索引?
下一篇 分布式事务面试题-请简要介绍什么是分布式事务以及它的主要作用是什么?

文章素材均来源于网络,如有侵权,请联系管理员删除。