MySQL常见面试题

MySQL

优化

  • 定位慢查询

  • SQL执行计划 :SQL分析能力

  • SQL优化经验:SQL优化

  • 索引

    • 存储引擎
    • 索引底层数据结构
    • 聚簇和非聚簇索引
    • 索引创建原则
    • 索引失效场景

其他

  • 事务相关:事务特性 隔离级别 MVVC
  • 主从同步原理:高并发
  • 分库分表:海量数据存储

一.索引

1.什么是索引?

索引是MySQL 高效获取数据的数据结构(有序)

在数据之外,数据库系统还维护着满足特定查找算法的数据结构(B+树 ),这些数据结构以某种方式指向数据,这样就可以在这些数据结构上实现高级查找算法.


2.索引创建的原则

  • 先陈述自己在工作中是如何运用的
  • 主键索引
  • 唯一索引
  • 根据业务创建索引(复合索引)

1.针对数据量比较大,且查询比较频繁的表建立索引

单表如果超过10w数据 (增加用户体验)

目的就是查询表的时候速度更快

2.针对常作为 查询条件的 where order by 分组group by 操作的字段建立索引
3.尽量去选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高

这里的区分度就不高,所以尽量不使用这种字段作为索引

4.如果是字符串,字段的长度较长,可以针对于字段的特点,建立前缀索引

5.尽量使用联合索引,减少单列索引 ,查询时,联合索引很多时候可以覆盖索引(避免回表),节省存储空间,提高查询效率

6.需要控制索引的数量,索引并不是多多益善,索引越多,维护成本就越大 ,从而会影响增删改的效率
7.如果**索引列不能存储null值,请在创建表时使用NOT NULL 去约束它,**当优化器知道每列是否包含NULL值时,可以更好的确定哪个索引最有效地用于查询.

总结:
  1. 数据量大且查询比较频繁的表
  2. 常作为查询条件的 字段
  3. 字段内容区分度比较高
  4. 内容比较长 使用前缀索引
  5. 尽量联合索引
  6. 要控制索引的数量
  7. 如果索引不能存储null值,在创建表时使用NOT NULL去约束它

3索引的底层数据结构是什么?

B+树

MySQL的InnoDB引擎采用的是B+树的数据结构来存储索引

  • 阶树更多,路径更短
  • 磁盘读写代价B+树更低, 非叶子结点只存储指针,叶子结点存储数据
  • B+树 便于扫库 和区间查询 ,叶子结点是一个 双向链表

数据结构对比

B树 是一种多叉路衡查找树,相当于二叉树,B树每个节点可以有多个分支,多叉.


4.B+树:

在B树的基础上的一种优化,更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构

  • 区别在于

非叶子结点只存储指针不存储数据

叶子结点才会真正的去存储数据

  1. 磁盘读写代价B+树更低
  2. 查询效率B+树更加稳定
  3. B+树便于扫库和区间查询

结点直接存在双向指针,相当于查询6 他可以一次性把所有的数据都拿到

总结:
  • 索引是帮助MySQL高效获取数据的数据结构
  • 是为了提高数据检索的效率,降低数据库的IO成本(不需要全表扫描)
  • 通过索引对数据进行排序,降低数据排序的成本,降低了CPU的消耗

5.什么是聚簇索引什么是非聚簇索引? 什么是回表?

什么是聚集索引,什么是二级索引(非聚簇索引)

什么是回表?

  • 聚餐索引

数据存储索引 放到一块,索引结构的叶子节点保存了行数据 ,必须有,而且只有一个

  • 二级索引

数据索引 分开存储,索引结构的叶子节点关联的对应的主键 , 可以存在多个

  • 聚簇索引选取规则:
  1. 如果存在主键,主键索引就是聚集索引
  2. 如果不存在主键,将使用唯一 UNIQUE 索引 作为聚集索引
  3. 如果表没有主键,或者没有合适的唯一索引,InnoDB会自动生成一个rowid作为隐藏的聚集索引

  • 回表查询

先通过二级索引找到对应的主键值,拿到主键再到聚集索引中查询出整行的数据,这个过程叫做回表查询

总结:
  • 聚集索引(聚簇索引):数据与索引放到一块,B+树的叶子节点保存的整行的数据,有且只有一个
  • 二级索引:数据与索引分开存储,B+树的叶子结点上存储的是对应的 主键,可以有多个
  • 什么是回表查询?
    • 通过二级索引找到对应的主键值,然后再到聚簇索引中查询出整行的数据,这个过程就是回表查询

6.什么情况下索引会失效?

7.如何去快速判断索引是否失效呢

执行计划explain

name status address

  • 违法了最左前缀法则

失效的情况:


  • 范围查询右边的列不能使用索引
  • 不要在索引列上进行运算操作,索引将失效

这里使用的substring进行了运算操作,且在索引列上

  • 字符串不加单引号,造成索引失效

查询的时候,没有对字符串加单引号,MySQL 查询优化器,会自动的进行类型转换, 造成索引失效

  • 模糊查询有可能会导致索引失效

总结:
  1. 违反了最左前缀法则: 使用复合索引,不能跳过某一列去查询
  2. 范围查询右边的列,不能使用索引
  3. 不要在索引上进行运算操作,索引会失效
  4. 字符串不加单引号,造成索引失效(类型转换)
  5. 以百分号% 开头的Like模糊查询,索引失效

二.MySQL中,如何定位慢查询

  • 聚合查询
  • 多表查询
  • 表数据量过大查询
  • 深度分页查询

表象:页面加载过慢、接口压测响应时间过长

方案一:开源工具

  • 调试工具:Arthas
  • 运维工具:Skywalking Prometheus

方案二:MySQL自带慢日志查询

执行慢的SQL执行在日志文件中

默认MySQL没有开启我们只需要在配置文件中开启就行

/etc/my.cnf

SQL 复制代码
# 开启MySQL慢日志查询开关
slow_query_log=1
# 设置慢查询的时间为2s SQL语句执行时间超过2s
long_query_time=2
# 配置完毕之后,通过指令重启MySQL服务器进行测试,查看慢日志文件中的记录
/var/lib/mysql/localhost-slow.log
总结:
  1. 介绍当时问题问题产生的场景
  2. 我们系统中采用了skywalking 可以检测出哪个接口,最终原因是sql的问题
  3. 在mysql中开启慢查询日志 ,一旦sql查询超过2s就会记录到日志中

三.sql语句执行的很慢,如何分析

SQL语句执行的很慢如何去分析呢?

  • 聚合查询
  • 多表查询
  • 表数据量过大查询: 添加索引
  • 深度分页查询

前三个可以通过 SQL执行计划找到慢的原因

EXPLAIN DESC命令获取到MySQL如何执行SELECT 语句信息

直接在select语句之前加上 explain/desc

这些字段不需要全部掌握

  • possible_key :当前sql可能会使用到的索引
  • key 当前sql 实际命中的索引
  • key_len 索引占有的大小
  • Extra 额外的优化建议

通过查看是否命中索引就是看 key 和key_len

出现了Using index condition 说明索引的使用是有优化的空间的

  • type sql连接的类型 null system const eq_ref ref range index all

越往左边性能越好

system :查询系统中的表

const:根据主键查询

eq_ref:主键索引查询或者唯一索引查询

ref:索引查询

range :范围查询

index:索引树扫描

all:全盘扫描


总结:

如果 SQL执行很慢,如何分析

  1. 我们可以采用MySQL自带的分析工具Explain
  2. 通过查看key 和key_len检查是否命中了索引 (索引本身存在是否失效的问题)
  3. 通过查看 type字段查看sql是否有进一步的优化空间,是否存在全索引扫描或者全盘扫描
  4. 通过extra建议来判断,是否出现了回表的情况,如果出现了可以添加索引或者修改返回字段来修复

四.谈谈SQL优化经验

  • 表的设计优化
  • 索引优化 : 参考优化创建原则和索引失效的原则
  • SQL语句优化
  • 主从复制、读写分离
  • 分库分表 后面专门章节介绍

1.表设计的优化

参考阿里开发手册 嵩山版本

2.SQL语句优化


  1. 避免使用select* 有可能会造成回表查询

  2. SQL语句要避免索引失效的写法

  3. 尽量 使用 union all 代替 unionunion会多一次过滤,效率低

  4. 避免在where子句中对字段进行表达式操作,例如substring 索引失效的时候讲到过 在索引字段上进行表达式操作

  5. Join 优化 能用 inner join 就不用 left join right join,如果必须使用一定要以小表驱动,内连接会对两个表进行优化,优先把小表放到外边,把大表放到里面。 left join 或 right join ,不会重新调整顺序

比如说:

外面的是小循环是小表,里面大循环是大表 3次连接1000次操作 和1000次连接3次操作

3.主从复制、读写分离

如果数据库的使用场景读的操作比较多的时候,为了避免写的操作造成的性能影响,可以采用读写分离的架构,为了解决数据库的写入,影响了查询的效率

在生成环境下 经常主从复制 读写分离

总结:
  1. 表设计优化,数据类型选择 char varchar
  2. 索引优化
  3. sql语句优化,避免索引失效,避免使用select *
  4. 主从复制,读写分离,不让数据的写入,影响读操作
  5. 分库分表

五.主从同步原理

数据库通过中间件连接了两个数据库,主库从库,主库负责写数据 从库负责读数据,那么如何进行同步的呢 原理是什么?

主从复制的核心就是二进制日志

二进制日志 binlog记录了所有的DDL 数据库定义语言,和DML 数据库操作语言,但不包括数据的查询 SELECT SHOW 语句

IOthread线程专门负责去读取 主库的binlog日志,读取完成之后就写入到从库的中继日志中relay log ,然后再由从库的SQLthread`线程去读取 中继日志的文件,然后再去执行 这样主库和从库的数据就保持了一致

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

六.分库分表

  • 前提: 单表数据量达到 1000w 和 20G
  1. 项目业务数据逐渐增多,或业务发展比较迅速
  2. 优化已经解决不了性能问题(主从读写分离,查询索引
  3. IO瓶颈(磁盘IO 网络IO),CPU瓶颈(聚合查询,连接数太多

1.拆分策略

垂直拆分
  1. 垂直分库
  2. 垂直分表
  • 垂直分库

以表为依据,根据业务将不同表拆分到不同的库中。


  • 垂直分表

以字段为依据,根据字段属性将不同字段拆分到不同表中

拆分规则

  1. 将不常用的字段单独放在一张表中
  2. 将text blog等大字段拆分出来放在附表中

比如感兴趣才把详情展示给用户

可能是在同一数据库下拆分成两张表

核心就是

  1. 冷热数据分离
  2. 减少IO 过度争抢,两表互不影响
水平拆分
  1. 水平分库:将一个库中的数据拆分到多个库中
  2. 水平分表:将一个表的数据拆分到多个表中(可以在同一个数据库)

路由规则

  • 按照id进行取模
  • 按id就是路由范围

多个库共同去存储业务的数据,海量数据存储问题,多个节点也能解决高并发的问题

水平分表


2.分库产生的问题

  • 分布式事务一致性问题
  • 跨界点关联的问题
  • 跨界点进行分页,排序函数
  • 主键避冲:比如水平分库 每个库中都存储相同的表 每个表中的数据都是自增的

为了解决增加分库分表的中间件

  1. MyCat
  2. sharding-sphere


七.事务(重要)

1.事务的特性是什么 ?

什么是事务?

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交活撤销操作,这些操作要么同时成功,要么同时失败

ACID:

  • 原子性:Atomicity:事务是不可分割的最小操作单元,要么全部成功,要么全部失败
  • 一致性:Consistencey:事务完成时,必须所有数据保持一致状态
  • 隔离性:I solation:数据库系统提供的隔离机制,保证事务在不受外部并发影响的独立环境下运行
  • 持久性:Durability:事务一旦提交或者回滚,他对数据库的改变就是永久的


2.并发事务带来了哪些问题?怎么解决?MySQL的默认隔离级别是?

  • 并发事务问题: 脏读 不可重复读 幻读
  • 隔离界别:读未提交 读已提交 可重复读 串行化

3.MySQL并发事务问题:

  • 脏读:一个事务读到了另外一个事务还没有提交的数据

事务A还没有提交但是事务B可以读到最新事务修改之后的数据, 一个事务读到了另外一个事务还没有提交的数据

  • **不可重复读:**一个事务先后读取同一条记录,但是两次读取的数据不同,称之为不可重复读.

  • 幻读:一个事务按照条件查询的时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 幻影

前提是已经解决了不可重复读的问题

一个事务内,查询同一条数据都是相同的数据 (1 ,4 相同) 但是执行3插入的时候依然提示存在这个数据这就像出现了幻觉一样

4.MySQL事务隔离界别:

  • 未提交度 (一般不用)
  • 读已提交: 可以解决脏读 不可重复读 幻读
  • 可重复读: MySQL默认隔离级别 可以解决不可重复读,脏读 不能解决幻读 Repeatable Read
  • 串行化: 可以解决所有问题,但是性能很低

事务隔离界别越往下,安全级别越高,性能越低


八.存储引擎

1.MySQL体系结构

存储引擎控制的就是MySQL数据的存储和提取的方式 ,服务器通过API和存储引擎来进行通信进行交互,Index索引是在存储引擎层实现的,不同引擎存储的结构是不一样的

InnoDB是MySQL 5.5版本之后默认的存储引擎

MySQL体系结构

存储引擎简介:

存储引擎特点:

存储引擎选择:




2.存储引擎简介:

什么是存储引擎?

默认存储引擎 : InnoDB

相当于发动机是一个机器的核心

存储引擎就是存储数据,建立索引,更新/查询数据等技术的实现方式 ,存储引擎是基于表而不是基于库的,所以存储引擎也可以被称为表类型

一个数据库中的多张表可以选择不同的存储引擎


查看当前数据库支持的存储引擎

复制代码
show engines;

InnoDB 默认存储引擎 支持事务 支持外键


3.InnoDB

MySQL中InnoDB是一种兼顾了高可靠性和高性能的通用存储引擎, 5.5 之后作为 默认存储引擎

  • DML操作支持ACID,和支持事务
  • 行级锁,提高并发访问性能
  • 支持外键 FOREIGH KEY,保证数据的完整性和正确性

文件


col 值得是一个一个的字段

4.MyISAM

MyISAM是MySQL早期的默认存储引擎

  • 不支持事务,不支持外键
  • 支持表锁,不支持行锁
  • 访问速度快


5.Memery

Memory 引擎的表数据是存储在内存中的,由于受到硬件问题,或断电问题的影响,只能将这些表作为临时表或缓存使用

  • 内存存放
  • hash索引(默认)

6.区别:


如何选择:


相关推荐
ruleslol3 分钟前
MySQL 工具使用指南
mysql
爱学java的ptt8 分钟前
mysql的存储引擎
数据库·mysql
小宇的天下16 分钟前
innovus Flip chip 产品设计方法(3)
数据库·windows·microsoft
龘龍龙23 分钟前
Python基础学习(十一)
python·学习·mysql
GalenZhang88841 分钟前
使用 Python SDK 将数据写入飞书多维表格
数据库·python·飞书·多维表格
云和数据.ChenGuang44 分钟前
GaussDB 期末考试题与面试题
数据库·opengauss·gaussdb·数据库期末试题
不屈的铝合金1 小时前
SQL 语言概述与数据库核心前置配置了解
数据库·sql·mysql·约束·sql 语句分类·字符集配置·校对规则
萧曵 丶1 小时前
可重复读(Repeatable Read)隔离级别下幻读产生的原因
数据库·sql·mysql
Antoine-zxt1 小时前
MySQL宕机日志迷局破解指南:从前台启动到精准排错
数据库·mysql·adb
松涛和鸣1 小时前
DAY47 FrameBuffer
c语言·数据库·单片机·sqlite·html