2024年 Java 面试八股文——MySQL篇

目录

1、Select 语句完整的执行顺序    难度系数:⭐

2、MySQL事务    难度系数:⭐⭐

3、MyISAM和InnoDB的区别    难度系数:⭐

4、悲观锁和乐观锁的怎么实现     难度系数:⭐⭐

5、聚簇索引与非聚簇索引区别     难度系数:⭐⭐

6、什么情况下mysql会索引失效    难度系数:⭐

7、B+tree 与 B-tree区别    难度系数:⭐⭐

8、数据库分表操作    难度系数:⭐

9、MySQL优化    难度系数:⭐

10、SQL语句优化案例    难度系数:⭐


1、Select 语句完整的执行顺序    难度系数:⭐

查询中用到的关键词主要包含如下展示,并且他们的顺序依次为

form...on...leftjoin...where...group by...avg()/sum()...having..select... order by...asc/desc...limit...

from: 需要从哪个数据表检索数据

where: 过滤表中数据的条件

group by: 如何将上面过滤出的数据分组算结果

order by : 按照什么样的顺序来查看返回的数据

2、MySQL事务    难度系数:⭐⭐

  1. 原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。
  2. 一致性:事务的执行使得数据库从一种正确状态转换成另一种正确状态
  3. 隔离性:在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,
  4. 持久性:事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,
  5. 事务的处理结果也会得到保存。

MySQL事务隔离级别

事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
读已提交(read-committed)

可重复读(repeatable0read)

可串行读(serializable)

3、MyISAM和InnoDB的区别    难度系数:⭐

1.MyISAM 存储引擎

主要特点:

MySQL5.5 版本之前的默认存储引擎,支持表级锁(表级锁是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁);不支持事务,外键。

适用场景:对事务的完整性没有要求,或以 select、insert 为主的应用基本都可以选用

MYISAM。在 Web、数据仓库中应用广泛。

特点:

1、不支持事务、外键

2、每个 myisam 在磁盘上存储为 3 个文件,文件名和表名相同,扩展名分别是

.frm-------存储表定义

.MYD --------MYData,存储数据

.MYI--------MYIndex,存储索引

2.InnoDB 存储引擎

主要特点:

MySQL5.5 版本之后的默认存储引擎;支持事务;

支持行级锁(行级锁是 Mysql 中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁);

支持聚集索引方式存储数据

4、悲观锁和乐观锁的怎么实现     难度系数:⭐⭐

悲观锁优化

  1. 确保使用索引
    如之前所述,使用 SELECT ... FOR UPDATE 时,应确保查询条件使用了索引,以避免锁定过多的行或整个表。

  2. 减少锁定时间
    尽量让事务保持简短,减少持有锁的时间,这样可以减少锁冲突的可能性。

  3. 使用更低级别的隔离级别
    根据业务需求,考虑使用如 READ COMMITTED 这样的较低隔离级别,而不是默认的 REPEATABLE READ。较低隔离级别可以减少锁定的范围和时间。

  4. 分批处理
    如果需要锁定大量数据,考虑使用分批处理的方式,每次只锁定和处理一部分数据。

乐观锁优化

  1. 合理设计版本号字段
    版本号字段应该是一个足够大的整数类型,以支持大量的更新操作。

  2. 避免并发更新同一行
    如果业务逻辑允许,尝试避免多个事务并发更新同一行数据,以减少版本冲突的可能性。

  3. 减少数据库往返次数
    在更新数据前,尽量通过业务逻辑判断是否需要更新,减少不必要的数据库查询和更新操作。

  4. 处理版本冲突
    当检测到版本冲突时,应有合理的重试机制或用户提示,指导用户如何处理冲突。

通用优化

  1. 监控和日志
    监控数据库锁的情况,记录锁等待和冲突事件,以便及时发现和解决性能问题。

  2. 使用连接池
    使用数据库连接池可以减少建立和关闭连接的开销,提高系统性能。

  3. 优化SQL语句
    对SQL语句进行优化,减少全表扫描,提高查询效率。

  4. 硬件和配置优化
    根据数据库服务器的硬件资源,合理配置数据库参数,如内存、缓存等,以充分发挥硬件性能。

针对乐观锁优化的示例

在更新商品库存时,你可以使用更高级的乐观锁策略,比如结合业务逻辑来减少版本冲突的可能性:

  1. 业务逻辑判断
    在尝试更新库存前,先检查库存是否足够。如果不足,则直接返回错误信息,避免不必要的数据库操作。

  2. 重试机制
    如果检测到版本冲突,可以设计一个重试机制。例如,等待一段时间后再次尝试更新,或者提示用户稍后重试。

  3. 批量更新
    如果有多个商品需要同时更新库存,可以考虑使用批量更新的方式,减少数据库操作的次数。

5、聚簇索引与非聚簇索引区别     难度系数:⭐⭐

都是B+树的数据结构

聚簇索引:将数据存储与索引放到了一块、并且是按照一定的顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的

非聚簇索引叶子节点不存储数据、存储的是数据行地址,也就是说根据索引查找到数据行的位置再取磁盘查找数据,这个就有点类似一本书的目录,比如我们要找第三章第一节,那我们先在这个目录里面找,找到对应的页码后再去对应的页码看文章。

优势:

1、查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询(非覆盖索引的情况下)效率要高

2、聚簇索引对于范围查询的效率很高,因为其数据是按照大小排列的

3、聚簇索引适合用在排序的场合,非聚簇索引不适合

劣势;

1、维护索引很昂贵,特别是插入新行或者主键被更新导至要分页(pagesplit)的时候。建议在大量插入新行后,选在负载较低的时间段,通过OPTIMIZETABLE优化表,因为必须被移动的行数据可能造成碎片。使用独享表空间可以弱化碎片

2、表因为使用uuId(随机ID)作为主键,使数据存储稀疏,这就会出现聚簇索引有可能有比全表扫面更慢,所以建议使用int的auto_increment作为主键

3、如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储的是主键值,过长的主键值,会导致非叶子节点占用占用更多的物理空间

6、什么情况下mysql会索引失效    难度系数:⭐

1. 使用了函数或表达式

当你在 WHERE 子句中对索引列使用函数或表达式时,MySQL 通常无法使用该索引。

SELECT * FROM users WHERE YEAR(created_at) = 2023;

在这个例子中,created_at 字段可能有一个索引,但是由于 YEAR() 函数的使用,该索引不会被使用。

2. 隐式类型转换

当比较不同类型的值时,MySQL 可能需要进行隐式类型转换,这可能导致索引失效。

SELECT * FROM users WHERE phone_number = '1234567890';

如果 phone_number 列是整数类型,但查询中使用的是字符串,MySQL 可能需要进行类型转换,从而不使用索引。

3. 使用了不等于 (!= 或 <>)

对于某些数据库和配置,使用不等于操作符可能导致索引失效。

SELECT * FROM users WHERE id != 100;

在某些情况下,MySQL 优化器可能决定全表扫描比使用索引更高效。

4. LIKE 查询以通配符开头

当使用 LIKE 查询且通配符 % 在模式字符串的开头时,索引通常不会被使用。

SELECT * FROM users WHERE name LIKE '%Smith';

这种情况下,MySQL 通常需要进行全表扫描。

5. OR 条件

在某些情况下,使用 OR 连接的条件可能导致索引失效,尤其是当 OR 的两侧都能使用不同的索引时。

SELECT * FROM users WHERE id = 1 OR email = 'example@example.com';

如果 id 和 email 都有索引,但查询优化器决定使用全表扫描比单独使用任一索引或合并使用两者更有效时,索引会失效。

6. 数据分布问题

如果表中数据分布不均匀,可能导致 MySQL 优化器决定不使用索引,因为全表扫描可能更快。

7. 索引选择性低

当索引的选择性很低(即索引的唯一值与总行数之比很小)时,MySQL 优化器可能会认为全表扫描更高效。

8. 使用了复合索引,但查询条件没有用到最左前缀

对于复合索引,查询条件必须使用索引的最左前缀,否则索引可能不会被使用。

-- 假设有一个复合索引 (first_name, last_name)  
SELECT * FROM users WHERE last_name = 'Smith';

在这个例子中,只使用了 last_name,没有用到复合索引的最左前缀 first_name,因此索引可能不会被使用。

9. 强制使用索引

尽管这不是索引失效的情况,但了解如何强制 MySQL 使用索引也是很有用的。你可以使用 FORCE INDEX 提示来强制 MySQL 使用特定的索引。

SELECT * FROM users FORCE INDEX (idx_name) WHERE name = 'John';

在这个例子中,即使优化器认为不使用 idx_name 索引可能更高效,MySQL 也会强制使用它。

为了避免索引失效,你应该:

  • 仔细选择和设计索引。
  • 监控查询执行计划,了解何时索引被使用或失效。
  • 避免在 WHERE 子句中对索引列使用函数或表达式。
  • 尽可能避免使用 LIKE 查询以通配符开头。
  • 在使用 OR 条件时,考虑是否可以重构查询或添加更多的索引来优化性能。
  • 定期检查数据分布和索引选择性,确保索引仍然有效。

 

7、B+tree 与 B-tree区别    难度系数:⭐⭐

1. 索引结构

索引是在 Mysql 的存储引擎(InnoDB,MyISAM)层中实现的, 而不是在服务层实现

的. 所以每种存储引擎的索引都不一定完全相同, 也不是所有的存储引擎都支持所有的索引

类型的, Mysql 目前提供了以下 4 种索引:

B+Tree 索引: 最常见的索引类型, 大部分索引都支持 B+树索引. Hash 索引: 只有 Memory 引擎支持, 使用场景简单. R-Tree 索引(空间索引): 空间索引是 MyISAM 引擎的一个特殊索引类型, 主要地理

空间数据, 使用也很少. S-Full-text(全文索引): 全文索引也是 MyISAM 的一个特殊索引类型, 主要用于全

文索引, InnoDB 从 Mysql5.6 版本开始支持全文索引.

2. BTree 结构
B+Tree 是在 BTree 基础上进行演变的, 所以我们先来看看 BTree, BTree 又叫多路
平衡搜索树, 一颗 m 叉 BTree 特性如下:
  1. 树中每个节点最多包含 m 个孩子.
  2. 除根节点与叶子节点外, 每个节点至少有[ceil(m/2)] 个孩子(ceil 函数指向上取整).
  3. 若根节点不是叶子节点, 则至少有两个孩子.

  每个非叶子节点由 n 个 Key 和 n+1 个指针组成, 其中 [ceil(m/2) -1 ] <= n <= m-1. 以 5 叉 BTree 为例, key 的数量: 公式推导 [ceil(m/2) -1 ] <= n <= m-1. 所以 2 <= n <= 4, 中间节点分裂父节点,两边节点分裂.

 

3.B+Tree 结构 

B+Tree 为 BTree 的变种, B+Tree 与 BTree 的区别:
1.B+Tree 的叶子节点保存所有的 key 信息, 依 key 大小顺序排列.
2.B+Tree 叶子节点元素维护了一个单项链表.
所有的非叶子节点都可以看作是 key 的索引部分.
由于 B+Tree 只有叶子节点保存 key 信息, 查询任何 key 都要从 root 走的叶子. 所以
B+Tree 查询效率更稳定.
Mysql 中的 B+Tree
MySql 索引数据结构对经典的 B+Tree 进行了优化, 在原 B+Tree 的基础上, 增加
了一个指向相邻叶子节点的链表指针, 就形成了带有顺序指针的 B+Tree, 提高区间访问的
性能

 

8、数据库分表操作    难度系数:⭐

水平分表

步长法:1000万一张表拆分

取模法:举例:根据用户id取模落入不能的表

垂直分表:大表拆小表。商品信息 spu_info spu_image ...

9、MySQL优化    难度系数:⭐

(1)尽量选择较小的列

(2)将where中用的比较频繁的字段建立索引

(3)select子句中避免使用‘*’

(4)避免在索引列上使用计算、not in 和<>等操作

(5)当只需要一行数据的时候使用limit 1

(6)保证单表数据不超过200W,适时分割表。针对查询较慢的语句,可以使用explain 来分析该语句具体的执行情况。

(7)避免改变索引列的类型。

(8)选择最有效的表名顺序,from字句中写在最后的表是基础表,将被最先处理,在from子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。

(9)避免在索引列上面进行计算。

(10)尽量缩小子查询的结果

10、SQL语句优化案例    难度系数:⭐

1) 定位执行效率慢的 sql 语句.
命令:show status like 'Com____',通过这条命令, 我们可以知道当前数据库是以查询为主
还是更新为主. 如果是查询为主, 就重点查询; 如果增删改多就重点优化写入操作.
explain + sql语句查询sql执行过程, 通过执行计划,我们能得到哪些信息:
A:哪些步骤花费的成本比较高
B:哪些步骤产生的数据量多,数据量的多少用线条的粗细表示,很直观
C:这条sql语句是否走索引
show profile 分析 SQL,可以查看所有 sql 语句的执行效率(所用时间). 前提是这个命令需要
被打开, 严格的说也就是打开这个命令后执行的所有 sql 语句, 它都能记录下执行时间, 并
展示出来. 可以通过这个命令分析哪些 sql 语句执行效率低. 耗时长, 就更有针对性的优化
这条 sql.
慢查询日志(常用的工具)
慢 查 询 日 志 记 录 了 所 有 执 行 时 间 超 过 参 数 long_query_time 的 sql 语 句 的 日 志 ,
long_query_time 默认为 10 秒(可以通过配置文件设置), 日志保存在 /var/lib/mysql/目录下,
有个 slow_query.log 文件,
2) 优化索引
2.1 索引设计原则
  • 索引的设计需要遵循一些已有的原则, 这样便于提升索引的使用效率, 更高效的使用索引.
  •  对查询频次较高, 且数据量比较大的表, 建立索引.
  • 索引字段的选择, 最佳候选列应当从 where 子句的条件中提取, 如果 where 子句中的组合
  • 比较多, 那么应当挑选最常用, 过滤效果最好的列的组合.
  •  使用唯一索引, 区分度越高, 使用索引的效率越高.
  • 索引并非越多越好, 如果该表赠,删,改操作较多, 慎重选择建立索引, 过多索引会降低表维 护效率.
  • 使用短索引, 提高索引访问时的 I/O 效率, 因此也相应提升了 Mysql 查询效率.
  • 如果 where 后有多个条件经常被用到, 建议建立符合 索引, 复合索引需要遵循最左前缀法 则, N 个列组合而成的复合索引, 相当于创建了 N 个索引. 复合索引命名规则 index_表名_列名 1_列名 2_列明 3
                比如:create index idx_seller_name_sta_addr on tb_seller(name, status, address)

  • 34
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值