MySQL 中的数据排序是怎么实现的?
参考链接:MySQL 中的数据排序是怎么实现的? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
- 排序过程中,如果排序字段命中索引,则利用索引排序。
- 反之,使用文件排序。
- 文件排序中,如果数据量少则在内存中排序,具体是使用单路排序或者双路排序。
- 如果数据大则利用磁盘文件进行外部排序,一般使用归并排序。
查询语句的执行
参考链接:详细描述一条 SQL 语句在 MySQL 中的执行过程。 - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
Notion – The all-in-one workspace for your notes, tasks, wikis, and databases.
1)通过连接器校验权限【权限校验】
- 如果用户名或者密码错误,客户端连接会立即断开
- 如果用户名密码认证通过,连接器会到权限表里面查出当前登陆用户拥有的权限。之后这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。
2)查询缓存 默认不开启,mysql 8.0 后就彻底移除这个功能了
3)解析优化
- 词法分析
- 语法分析
- 预处理器
4)查询优化器
查询优化器的目的就是根据解析树生成不同的执行计划(Execution Plan),然后选择一种最优的执行计划,MySQL 里面使用的是基于开销(cost)的优化器,哪种执行计划开销最小,就用哪种
5)执行计划
6)利用执行器,调用引擎层查询数据,返回结果集给客户端
MySQL 的存储引擎有哪些?它们之间有什么区别?
参考链接:MySQL 的存储引擎有哪些?它们之间有什么区别? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
MySQL 的主要存储引擎包括:
1)InnoDB(MySQL 默认存储引擎):支持事务、行级锁和外键。提供高并发性能,适用于高负载的 OLTP 应用。数据以聚集索引的方式存储,提高检索效率
2)MyISAM:不支持事务和外键,使用表级锁。适合读取多、更新少的场景,如数据仓库。具有较高的读性能和较快的表级锁定
3)MEMORY:数据存储在内存中,速度快,但数据在服务器重启后丢失。适用于临时数据存储或快速缓存
4)NDB (NDBCluster):支持高可用性和数据分布,适合大规模分布式应用。提供行级锁和自动分区
5)ARCHIVE:用于存储大量历史数据,支持高效的插入和压缩。不支持索引,适合日志数据存储
MySQL 的索引类型有哪些?
参考链接:MySQL 的索引类型有哪些? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
从数据结构角度来看,MySQL 索引可以分为以下几类:
- B+树索引(MySQL 默认使用的索引)
- 哈希索引
- 倒排索引(Full-Text)
- R-树索引(多维空间树)
从常见的基于 InnoDB B+ 树索引角度来看,可以分为:
- 聚簇索引(主键索引)
- 非聚簇索引(非主键索引)
从索引性质的角度来看,可以分为:
- 普通索引
- 主键索引
- 联合索引
- 唯一索引
- 全文索引
- 空间索引
MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别?
参考链接:MySQL InnoDB 引擎中的聚簇索引和非聚簇索引有什么区别? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
聚簇索引叶子节点中存储的是完整的数据行,每个表只能有一个聚簇索引,非聚簇索引叶子节点中存储的是数据行的主键和对应的索引列,一个表可以有多个非聚簇索引
MySQL 中的回表是什么?
参考链接:MySQL 中的回表是什么? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
"回表" 是指在使用二级索引(非聚簇索引)作为条件进行查询时,由于二级索引中只存储了索引字段的值和对应的主键值,无法得到其它数据。如果要查询数据行中的其它数据,需要根据主键去聚簇索引查找实际的数据行,这个过程被称为回表
MySQL 索引的最左前缀匹配原则是什么?
参考链接:MySQL 索引的最左前缀匹配原则是什么? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
MySQL 索引的最左前缀匹配原则指的是在使用联合索引时,查询条件必须从索引的最左侧开始匹配。如果一个联合索引包含多个列,查询条件必须包含第一个列的条件,然后是第二个列,以此类推。
MySQL 的覆盖索引是什么?
参考链接:MySQL 的覆盖索引是什么? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
MySQL 的覆盖索引(Covering Index)是指二级索引中包含了查询所需的所有字段,从而使查询可以仅通过访问二级索引而不需要访问实际的表数据(主键索引)。
MySQL 的索引下推是什么?
参考链接:MySQL 的索引下推是什么? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
索引条件下推(Index Condition Pushdown,ICP)说白了就是过滤的动作由下层的存储引擎层通过使用索引来完成,而不需要上推到Server层进行处理
在 MySQL 中建索引时需要注意哪些事项?
参考链接:在 MySQL 中建索引时需要注意哪些事项? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
1)不能盲目的建立索引:索引会占用空间,且每次修改的时可能都需要维护索引的数据,消耗资源。
2)对于字段的值有大量重复的不要建立索引:比如说:性别字段,在这种重复比例很大的数据行中,建立索引也不能提高检索速度。但是也不绝对,例如定时任务的场景,大部分任务都是成功,少部分任务状态是失败的,这时候通过失败状态去查询任务,实际上能过滤大部分成功的任务,效率还是可以的。
3)对于一些长字段不应该建立索引:比如 text、longtext 这种类型字段不应该建立索引。因为占据的内存大,扫描的时候大量加载至内存中还耗时,使得提升的性能可能不明显,甚至可能还会降低整体的性能,因为别的缓存数据可能因为它被踢出内存,下次查询还需要从磁盘中获取。
4)当数据表的修改频率远大于查询频率时,应该好好考虑是否需要建立索引。因为建立索引会减慢修改的效率,如果很少的查询较多的修改,则得不偿失。
5)对于需要频繁作为条件查询的字段应该建立索引。在 where 关键词后经常查询的字段,建立索引能提高查询的效率,如果有多个条件经常一起查询,则可以考虑联合索引,减少索引数量。
6)对经常在 order by、group by、distinct 后面的字段建立索引。这些操作通常需要对结果进行排序、分组或者去重,而索引可以帮助加快这些操作的速度。
MySQL 中使用索引一定有效吗?如何排查索引效果?
参考链接:MySQL 中使用索引一定有效吗?如何排查索引效果? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
索引不一定有效
- 例如查询条件中涉及的列未被索引、低基数列索引效果不佳(比如性别),或查询条件复杂且不匹配索引的顺序
- 对于小表,MySQL可能选择全表扫描而非使用索引,因为全表扫描的开销可能更小
排查索引效果的方法
使用 EXPLAIN
命令:通过在查询前加上EXPLAIN
,可以查看 MySQL 选择的执行计划,了解是否使用了索引、使用了哪个索引、估算的行数等信息。
主要观察 EXPLAIN
结果以下几点:
- type(访问类型):这个属性显示了查询使用的访问方法,例如
ALL
、index
、range
等。当查询使用索引时,这个属性通常会显示为index
或range
,表示查询使用了索引访问。如果这个值是ALL
,则表示查询执行了全表扫描,没有使用索引。 - key(使用的索引):这个属性显示了查询使用的索引,如果查询使用了索引,则会显示索引的名称。如果这个值是
NULL
,则表示查询没有使用索引。 - rows(扫描的行数):这个属性显示了查询扫描的行数,即查询返回的行数,需要评估下扫描量。
MySQL 索引什么时候会失效
参考链接:MySQL 中使用索引一定有效吗?如何排查索引效果? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
简短总结
- 使用了联合索引却不符合最左前缀
- 索引上使用了运算:比如
where id + 1 = 2
- 索引上使用了函数:比如
where LOWER(name) like 'cong%'
- like 的随意使用:比如
name = like '%飞'
- or 的随意使用
- 随意的字段类型使用【隐式转换】
- 表中两个不同字段进行比较
- 使用了 != 、<>、is not null
- order by 后面不是 主键 或者 覆盖索引
1)使用了联合索引却不符合最左前缀
假设联合索引 (name, phone) ,这个时候如果查询条件只有一个 phone,那么这个时候只会进行全盘扫描,因为联合索引的B+树数据页内的记录首先按照 name 字段进行排序,name 字段相同的情况下,再按照 phone字段进行排序,所以,如果我们直接使用 phone 字段进行搜索,无法利用索引的顺序性
但是一旦加上 name 的搜索条件,就会使用到联合索引,而且不需要在意 name 在 where 子句中的位置,因为查询优化器会帮我们优化
create table user(
id int primary key auto_increment,
name varchar(20) not null,
phone varchar(20) not null,
age int not null
);
# 创建联合索引
create index name_phone_index on user(name,phone);
# 测试结果: type = ref; key = name_phone_index
explain select * from user where name = '张三' and phone = '134***';
# 测试结果: type = ref; key = name_phone_index
explain select * from user where phone = '134***' and name = '张三';
但是也会有一种情况就是,假设联合索引已经覆盖所有要查询的字段,并且查询条件中涉及的列也是联合索引中的列,那么也是会直接使用联合索引的
因为主键索引存储了所有的数据,包括数据行相关的事务ID、回滚指针等等。而二级索引不包含这些,它只有主键值和索引列的值。所以相对而言直接读取联合索引开销会更小一些
create table user(
id int primary key auto_increment,
name varchar(20) not null,
phone varchar(20) not null,
age int not null
);
# 创建联合索引
create index name_phone_index on user(name,phone);
# 测试结果: type = index; key = name_phone_index (使用了二级索引)
# 如果只是查询联合索引中能覆盖查询的列并且查询条件中只有对应联合索引的列, 那么直接使联合索引
explain select name from user where phone = '134***';
# 测试结果: type = ALL; key = null
# 全表查询, 因为 age 不包含在二级索引中
explain select name from user where age = '12'
2)索引上使用了运算
例如这个 SQL select * from user where id + 3 = 8
。这样会导致全表扫描计算 id
的值再进行比较,使得索引失效
3)索引上使用了函数
例如:select * from user where LOWER(name) like 'cong%';
。这样也会导致索引失效,索引参与了函数处理,会导致去全表扫描
4) like 的随意使用
例如:select * from user where name like '%cong%';
因为索引是从左到右来进行排序查找的,占位符直接放在了最左边开头,会导致直接全表扫描,这种情况就会导致索引失效
5)or 的随意使用
user
当前只有一个索引 name
。此时执行以下SQL :select * from user where name= 'cong' or age = 18;
这也会导致索引失效,因为 age 没有索引
6)随意的字段类型使用【隐式转换】
比如 name 的 字段类型是 varchar,那么查询条件中把使用 int 类型,就会涉及隐式转换,select * from user where name = 1;
,在代码中涉及 隐式转换 !等于 select * from user where CAST(name AS signed int) = 1;
,这就变成了索引上使用了函数,导致索引失效。
7)表中两个不同字段进行比较
例如这样的SQL :select * from user where id > age;
,将 id
跟 age
字段做了比较,好家伙!索引失效!
8)使用了 != 、<>、is not null
例如这样的 SQL :select * from user where name != 'cong'
,可能会导致索引失效,这个场景下的 SQL 是否失效是根据查询到的数据集决定的,当数据大了的时候可能会导致索引失效
9)order by 后面不是 主键 或者 覆盖索引
当 order by
后面跟的 不是主键 或者 覆盖索引 会导致不走索引。
MySQL 中的索引数量是否越多越好?为什么?
参考链接:MySQL 中的索引数量是否越多越好?为什么? - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
索引并不是越多越好。因为索引不论从时间还是空间上都是有一定成本的
时间代价
每次对表中的数据进行增删改 (INSERT、UPDATE 或 DELETE) 的时候,索引也必须被更新,这会增加写入操作的开销(索引更新,比如聚簇索引和非聚簇索引)。并且 B+ 树可能会有页分裂、合并等操作,时间开销就会更大。
还有一点需要注意:MySQL 有个查询优化器,它需要分析当前的查询,选择最优的计划,这过程就需要考虑选择哪个索引的查询成本低。如果索引过多,那么会导致优化器耗费更多的时间在选择上,甚至可能因为数据的不准确而选择了次优的索引。
空间代价
每建立一个二级索引,都需要新建一个 B+ 树,默认每个数据页都是 16kb,如果数据量很大,索引又很多,占用的空间可不小。
请详细描述 MySQL 的 B+ 树中查询数据的全过程
参考链接:请详细描述 MySQL 的 B+ 树中查询数据的全过程 - MySQL 面试题 - 面试鸭 - 程序员求职面试刷题神器
1)数据从根节点找起,根据键值的大小确定左子树还是右子树,从上到下最终定位到叶子节点
2)叶子节点存储实际的数据行记录,但是一页有 16kb 大小,存储的数据行不止一条
3)叶子节点中数据行以组的形式划分,利用页目录结构,通过二分查找可以定位到对应的组
4)定位组后,利用链表遍历就可以找到对应的数据行
语雀文档链接:https://www.yuque.com/heyyall/summary/msuh5tql887unpig
正在找工作或者想要提升技术的程序员都可以去试试这款刷题神器【面试鸭】。你能想到的各种题目都被整理得明明白白,再也不用自己到处找七零八落的资料。8000多道超全题库+高频题+大厂面试官原创题解+真实面经,绝对的求职秘密武器,扫码即可体验⬇️
标签:面试题,Java,name,面试,查询,索引,user,MySQL From: https://blog.csdn.net/a2497_282263/article/details/143258189