Java后端面试:MySQL面试篇(底层事务、SQL调优)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:Java后端面试:Redis面试篇(原理+场景题)
📚订阅专栏:Java后端面试
希望文章对你们有所帮助

MySQL可能是面试最常问的了,经常喜欢问MySQL的优化,包括定位慢查询、SQL执行计划、索引、优化经验等等,相关的详细原理也可以看之前的专栏:
MySQL进阶
在这里更多是对常见面试题做个总结。

MySQL面试篇(底层事务、SQL调优)

  • SQL优化
    • 定位慢查询
    • SQL语句执行慢,如何分析(SQL执行计划)
    • 索引及其底层
    • 聚簇索引、非聚簇索引、回表查询
    • 覆盖索引、超大分页查询
    • 索引创建原则
    • 索引失效的情况
    • SQL优化经验
  • MySQL事务
    • 事务特性
    • 并发事务问题、隔离级别
    • undo log与redo log的区别
    • 解释MVCC
    • MySQL主从同步原理
    • MySQL分库分表

SQL优化

定位慢查询

一般的慢查询可能是这些情况:

1、聚合查询
2、多表查询
3、表数据量过大查询
4、深度分页查询

表象:页面加载过慢、接口压测的响应时间过长(超过1s)。

定位慢查询可以通过开源工具,但是我没有用过,就不介绍了,还有一种慢查询的定位方式是通过MySQL自带的慢查询日志

慢查询日志记录了所有执行时间超过指定参数(单位:秒)的所有SQL语句的日志
若要开启慢查询日志,需要修改配置文件

# 开启慢查询开关
slow_query_log = 1
# 设置慢查询时间为2s
long_query_time = 2

SQL语句执行慢,如何分析(SQL执行计划)

若这个SQL语句执行的很慢,如何分析呢?

通过SQL执行计划,可以找到SQL执行慢的原因

可以采用EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息,只需要在select之前加上这两种关键词。
查询出来后需要关注的字段:

1、possible_key:当前SQL可能会用到的索引
2、key:当前SQL实际命中的索引
3、key_len:索引占用的大小
4、Extra:额外的优化建议
(1)Using where;Using Index:查找过程用了索引,需要的数据在索引列中能找到,无需回表查询
(2)Using index condition:查找过程用了索引,但需要回表查询
5、type:SQL的连接类型,性能由好到差为NULL、system、const、eq_ref、ref、range、index、all
(1)system:查询系统中的表
(2)const:根据主键查询
(3)eq_ref:主键索引查询或唯一索引查询
(4)ref:索引查询
(5)range:范围查询
(6)index:索引树扫描
(7)all:全盘索引

其中,我们可以通过key和key_len检查是否命中索引(索引是否有失效的情况)通过type查看SQL是否有进一步的优化空间,通过extra查询是否有回表的情况,如果出现则可以通过添加索引或者修改返回的字段来修复

索引及其底层

1、索引的作用:

索引是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库还维护了一个B+树,可以在B+树上实现高级查找算法。
若没有索引,查找数据可能要遍历整张表,效率过于低。

2、为什么不用二叉搜索树、红黑树、或者B树?

(1)二叉搜索树:最坏的二叉树(按顺序插入),相当于退化成了一个链表,查询效率与全盘扫描没区别(复杂度不稳定)
(2)红黑树:虽然复杂度更稳定了,但是如果数据特别大的话,由于红黑树每个结点只有两个子结点,还是会导致树太高,查询效率低
(3)B树:多叉路衡查找树,有很多分支(若最大度数为5,则每个节点最多存储4个key)。
(4)B+树:比起B树更适合实现外存储索引结构,相比较B树,B+树只有叶子节点才会存储数据,非叶子节点只是一个导航定位的作用,除此之外,叶子节点还加上了双向链表。InnoDB引擎就是用B+树来实现的索引结构。
B树与B+树的对比:
①磁盘读写代价B+树更低;②查询效率B+树更稳定;③B+树更便于扫库和区间查询(由于双向链表,只需要根据区间的左边界查,然后直接扫链表就好了)

聚簇索引、非聚簇索引、回表查询

1、什么是聚簇索引和非聚簇索引?(其实还有一种称呼是聚集索引和二级索引)

1、聚簇索引(聚集索引):将存储数据域索引放在一起,索引的叶子节点保存了行数据。必须要有聚集索引而且只能有一个
2、非聚簇索引(二级索引):将数据与索引分开存储,索引的叶子节点关联的是对应的主键。可以存在多个。

2、聚集索引的选取规则?

1、存在主键,则主键索引就是聚集索引
2、不存在主键,则第一个唯一索引作为聚集索引
3、没有主键和唯一索引,则InnoDB引擎会自动生成rowid作为隐藏的聚集索引

3、什么是回表查询

先通过二级索引找到对应的主键值,到聚集索引中查找整行数据并返回,这个过程就是回表查询

覆盖索引、超大分页查询

覆盖索引:查询使用了索引,并且需要返回的列在该索引树中已经能够全部找到。

例如,id为主键索引,name为普通索引,则下列指令符合覆盖索引

select id, name from tb_user where name = 'wxj';
select * from tb_user where id = 2; # 查询聚集索引,叶子节点就是一整行的数据,也算覆盖索引

如果不符合覆盖索引,例如select id,name,gender from tb_user where name='Arm',首先在二级索引中查询name字段,查询完成之后由于叶子节点只包含了id和name,所以还需要进行回表查询,这时候的效率就会很低。这也就是为啥要尽量避免select *,除非查询的条件是根据主键的。

MySQL超大分页处理:当数据量很大的时候用limit做分页查询,越往后,分页查询的效率就越低。这是因为limit底层会给前面的记录都先排序,再去查询,这种排序代价可能会很大。

优化思路:一般分页查询时,通过创建覆盖索引能够比较好的提高性能,可以通过覆盖索引+子查询的形式进行优化。

select *
from tb_sku t,(select id from tb_sku order by id limit 9000000,10) a
where t.id = a.id;

索引创建原则

1、针对数据量较大,且查询频繁的表建立索引(增加用户体验)
2、针对常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引
3、尽量选择区分度高的列作为索引,尽量建议唯一索引,区分度越高,使用索引的效率就越高
4、若是字符串类型的字段,可以建立前缀索引
5、尽量使用联合索引,减少单列索引,因为查询的时候联合索引很多时候可以覆盖索引,避免回表,提高查询效率
6、控制索引的数量,索引越多,维护的代价就越大

重点是1、2、5、6条,这在面试的时候肯定要讲到。

索引失效的情况

1、违背最左前缀法则

若索引了多列,要遵守最左前缀法则。也就是查询从索引的最左前列开始,否则索引会完全失效。并且最好不跳过索引中的列,否则会部分失效

2、范围查询右边的列,不能使用索引

# address是范围查询status > '1'的列,address失效
explain select * from tb_seller where name = '小米科技' and status > '1' and address = '北京市';

3、在索引列上进行运算操作,索引会失效

select * from tb_seller where substring(name,3,2) = '科技';

4、字符串不加单引号,可能会索引失效(因为底层可能会出现类型转换)

5、以%开头的Like模糊查询,索引失效

若仅仅是尾部模糊查询,索引不会失效。如果是头部模糊查询,索引失效

SQL优化经验

从五个方面回答这个问题:

1、表的设计优化(参考了阿里的开发手册)
(1)设置合适的数值(tinyint、int、bigint)
(2)设置合适的字符串类型(char和varchar,其中char定长效率高,varchar长度可变但效率偏低)
2、索引优化(优化的原则、索引失效的情况)
3、SQL语句优化
(1)避免使用select *
(2)避免索引失效
(3)尽量用union all代替union,因为union会增加一次过滤
(4)避免在where子句中对表达式进行表达式操作(因为也会出现索引失效,如substring)
4、主从复制、读写分离:若读的操作很多,为了避免写操作造成的性能影响,可以使用读写分离,其解决的
5、分库分表

MySQL事务

事务特性

ACID特性:

(1)原子性
(2)一致性
(3)隔离性
(4)持久性

并发事务问题、隔离级别

并发事务问题有哪些?解决的方法是什么?

并发事务问题:脏读、不可重复读、幻读
隔离级别:读未提交、读已提交、可重复读(默认)、串行化

并行事务问题:

问题描述
脏读一个事务读到另外一个事务还没有提交的数据
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同
幻读一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现了这行数据已经存在,好像出现了“幻影”(插入的时候显示存在,再次查询还是查不到,因为此时已经解决了不可重复读)

解决方案:对事务进行隔离

1、读未提交:三种问题都存在
2、读已提交:解决脏读
3、可重复读:解决脏读和不可重复读(默认)
4、串行化:三种问题都解决

级别越高,越安全,但是性能越低。一般情况下是不会用串行化的,如果一定要在默认(可重复读)的隔离级别下解决幻读,需要使用MVCC。

undo log与redo log的区别

需要记住两个概念:

缓冲池:主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查时,先操作缓冲池数据(若没有就从磁盘加载并缓存),并以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度
数据页:InnoDB存储引擎磁盘管理的最小单元,每个页的默认大小为16KB,页中存储的是行数据

redo log:重做日志,记录的是事务提交时数据页的物理修改,用来实现事务的持久性
该日志由重做日志缓冲重做日志文件组成,前者在内存中,后者在磁盘中。当事务提交后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘发生错误时,进行数据恢复。

如果业务出现错误导致数据不同步,当然也可以直接把缓冲池的数据加载回磁盘,但是这样的方式将会很影响性能。
而由于日志文件都是追加的,所以使用日志文件的这种方式的磁盘IO都是顺序的,就会提高效率。这种方式称为WAL(先写日志)

undo log:回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚MVCC(多版本并发控制)。undo log与redo log记录物理日志不同,它是逻辑日志

当delete一条记录时,undo log会记录一条insert记录,反之亦然。
当update时,会记录一条相反的update记录。
当执行rollback时,可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

也就是说,undo log用于实现事务的一致性和原子性

总结:

1、redo log记录的是数据页的物理变化,服务宕机可以用来同步数据
2、undo log记录的是逻辑日志,当事务回滚时,通过逆操作恢复数据
3、redo log保证了事务的持久性,undo log保证了事务的原子性和一致性

解释MVCC

undo log和redo log保证了事务的原子性、持久性、一致性,而隔离性是如何保证的呢?

隔离性由两个因素决定:
1、锁:排他锁(若一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁)
2、MVCC:多版本并发控制

解释一下MVCC?(事务中的隔离性是如何保证的呢?)

1、MVCC是多版本并发控制。指维护一个版本的多个数据,使得读写操作没有冲突。
2、MVCC的具体实现,主要依赖于数据库记录中的隐藏字段undo log日志readView
(1)隐藏字段:
①DB_TRX_ID:最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID
②DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本
③DB_ROW_ID:隐藏主键,若表结构没有指定主键,将会生成该隐藏字段
(2)undo log:回滚日志,在增删改的时候产生的便于数据回滚的日志。
需要重点理解undo log版本链,可以看我之前的MySQL进阶的专栏,里面有详细解析。
(3)readView(读视图):是快照读(记得区分一下什么是当前读,什么是快照读)SQL执行时MVCC提取数据的一句,记录并维护系统当前活跃的事务(未提交的)id。readView包含四个核心字段:
①m_ids:当前活跃的事务ID集合
②min_trx_id:最小活跃事务ID
③max_trx_id:预分配事务ID,即当前最大事务ID+1
④creator_trx_id:readView创建者的事务ID
而具体的工作方式,需要依赖undo log版本链,具体依旧看我之前的文章。

需要记住,不同的隔离级别下,生成ReadView的时机不同
(1)READ COMMITED:每次执行快照读时生成readView
(2)Repeatable Read:仅在第一次快照读生成readView,后面复用(就是因为这样,才解决了不可重复读)

MySQL主从同步原理

主从同步无非就是要实现主结点到从结点的复制操作,即主从复制。
MySQL主从复制的核心是二进制日志(BINLOG),记录了所有的DDL和DML语句。
主从复制的步骤分为三步:

1、主库在事务提交时,会把数据变更记录在二进制文件BINLOG中
2、从库读取主库的二进制日志文件BINLOG,写入到从库的中继日志Relay log
3、从库重做中继日志中的事件,将改变反映它自己的数据

MySQL分库分表

我自己做的项目还没有用到海量数据,所以我根本没有用过分库分表,既然没有,面试被问到就说自己了解,能懂一些概念就好了。

为什么要用分库分表?

当使用主从分离、读写分离(主库写数据,从库读数据),可以分担访问的压力,但是主库和从库的表都是一样的,海量数据下不合适。
单表的数据量达到了1000W,优化就已经解决不了性能的问题了,而且还会出现IO瓶颈、CPU瓶颈

分库分表的分类?

1、垂直拆分
(1)垂直分库:以表为依据,根据业务把不同表拆到不同库中。
(2)垂直分表:以字段为依据,根据字段属性将不同字段拆分到不同表中。(例如把大字段、不常用的字段拆分出来单独放在一张表)
2、水平拆分
(1)水平分库:将一个库的数据拆分到多个库中
(2)水平分表:将一个表的数据拆分到多个表中(可以在同一个库内)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750144.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu 虚拟机安装

最小化安装后常用工具 sudo apt-get install vim# ifconfig apt install net-tools # nload apt install nload # 很多都要用到 apt install build-essential # 开发相关 apt install gcc gapt install iproute2 ntpdate tcpdump telnet traceroute \ nfs-kernel-server nfs…

Leetcode 第 126 场双周赛 Problem D 求出所有子序列的能量和(Java + 数学 + 01背包变种)

文章目录 题目思路Java 数学 01背包变种第一步:第二步:第三步: 复杂度Code 题目 Problem: 100241. 求出所有子序列的能量和给你一个长度为 n 的整数数组 nums 和一个 正 整数 k 。一个整数数组的 能量 定义为和 等于 k 的子序列的数目。请…

Node.js 自带的 http 模块来实现一个简单的本地服务器

1.创建一个 server.js 文件: const http require(http); const fs require(fs); const path require(path);const server http.createServer((req, res) > {// 获取请求的文件路径const filePath path.join(__dirname, dist, req.url);// 读取文件内容并返…

Ubuntu 14.04:安装 PaddleOCR 2.3

目录 一、说明 1.1 如何选择版本 1.2 查看 github 中的 PaddleOCR 版本 二、安装 2.1 安装前环境准备 2.2 下载包 2.3 解压 2.4 安装依赖库 异常处理:Read timed out. 2.5 下载推理模型:inference 2.5.1 模型存放位置 2.5.2 模型下载链接 2.5.…

JVM学习-底层字节码的执行过程

目录 1.一个简单的程序分析 2. a,a,a--在JVM中的执行过程 3. 一个好玩的xx 4.方法调用的字节码分析、多态的实现、对象头 5. try-catch-finally的字节码分析 5.1 try-catch 5.2 try-catch-finally 5.3特殊情况 5.3.1 try和finally块中都出现了re…

【Miniconda】基于conda避免运行多个PyTorch项目时发生版本冲突

【Miniconda】基于conda避免运行多个PyTorch项目时发生版本冲突 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程👈 希望得到…

SQL的执行与优化

文章目录 MySQL查询原理与优化一、select语句的执行顺序二、join 的执行与优化1、驱动表 & 被驱动表2、Simple Nested Loop Join3、Index Nested Loop Join4、Block Nested Loop Join5、Hash Join6、join 优化小结 三、on 与 where 对比四、group by 的执行与优化1、group …

刚刚离乳的幼猫该如何选择猫粮品牌?

亲爱的猫友们,当你家的幼猫刚刚离乳,准备踏入猫粮的世界时,如何选择一款合适的猫粮品牌确实是个让人头疼的问题。🐾 别担心,今天我就来为大家推荐一款值得信赖的幼猫粮——福派斯幼猫粮。 1️⃣ 考虑幼猫的营养需求 幼…

macOS系统中通过brew安装MongoDB

Macos 修改目录权限: sudo chmod -R 777 你的文件夹 本文使用homebrew进行安装简单,因为从官网下载安装包并手动安装需要移动安装包到合适的目录下并配置环境变量等一大堆操作后才能使用数据库(若没有安装过brew请自行百度进行安装brew&am…

【leetcode刷题之路】面试经典150题(7)——分治+Kadane 算法+二分查找+堆

文章目录 16 分治16.1 【分治】将有序数组转换为二叉搜索树16.2 【归并排序】排序链表16.3 【分治】建立四叉树16.4 【暴力】合并 K 个升序链表 17 Kadane 算法17.1 【动态规划】最大子数组和17.2 【动态规划】环形子数组的最大和 18 二分查找18.1 【二分】搜索插入位置18.2 【…

ArkTs的资源Resource类型怎么转为string

使用ResourceManager同步转换 请参看:ResourceManager.getStringSync9 例子: try { let testStr: string this.context.resourceManager.getStringSync($r(app.string.test).id); } catch (error) { console.error(getStringSync failed, error code…

【四 (5)数据可视化之 Pyecharts常用图表及代码实现 】

目录 文章导航一、介绍[✨ 特性]二、安装Pyecharts三、主题风格四、占比类图表1、饼图2、环形图3、玫瑰图4、玫瑰图-多图5、堆叠条形图6、百分比堆叠条形图 五、比较排序类1、条形图2、雷达图3、词云图4、漏斗图 六、趋势类图表1、折线图2、堆叠折线图3、面积图4、堆叠面积图 七…

【AI】Ubuntu系统深度学习框架的神经网络图绘制

一、Graphviz 在Ubuntu上安装Graphviz,可以使用命令行工具apt进行安装。 安装Graphviz的步骤相对简单。打开终端,输入以下命令更新软件包列表:sudo apt update。之后,使用命令sudo apt install graphviz来安装Graphviz软件包。为…

MySQL语法分类 DQL(1)基础查询

//语法 select 字段列表 from 表名列表 where条件列表 group by分组字段 having 分组后的条件 order by排序 limit 分页限定为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),ma…

springboot/ssm图书管理系统Java图书馆借阅管理系统web图书借阅系统

springboot/ssm图书管理系统Java图书馆借阅管理系统web图书借阅系统 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&#…

将 OpenCV 与 Eclipse 结合使用(插件 CDT)

返回:OpenCV系列文章目录(持续更新中......) 上一篇:将OpenCV与gcc和CMake结合使用 下一篇:OpenCV4.9.0在windows系统下的安装 警告: 本教程可以包含过时的信息。 先决条件 两种方式,一种…

CODESYS开发教程13-长字符串处理

摘要:这是一篇写给新手的关于CODESYS开发环境的小白教程,一看就懂...... 在以前的《CODESYS开发教程7-字符串及其基本操作》教程中,介绍了字符串及其基本操作,有朋友看了以后觉得不过瘾,希望有一些关于字符串的更加深入…

Android Framework基础之C语言入门

C语言入门详解 一、C语言简介 C语言是一种通用的、过程式的编程语言,支持结构化编程、词法变量作用域和递归等功能,是迄今为止最为强大的编程语言之一。C语言设计提供了能轻松实现底层的访问,通常用于系统软件开发,应用程序的一…

ES系列之快照与恢复

概述 原理 ES底层核心基于lucene,一个分片即是一个lucene对象实例,ES快照(snapshot)本质是对lucene物理文件的拷贝。 增量快照的核心是比较lucene segements不可变文件信息,每次创建快照时会建立一个IndexCommit提交点,包含seg…

javaweb员工健康管理监护系统

项目演示视频 (链接:https://pan.baidu.com/s/1WliYEUH4c0HVB7s0-1WDUA 提取码:1234 --来自百度网盘超级会员V5的分享) 该项目所用到技术 java ssh框架 3:该项目的用到的开发工具? eclipse和idea都可以、m…