MySQL面试总结
MySQL面试
- 1、了解SQL的执行顺序吗?
- 2、一条SQL查询非常慢,我们怎么去排查和优化?
- 3、对SQL慢查询会考虑哪些优化?
- 4、事务的4大特性(ACID)?
- 5、脏读、不可重复读、幻读
- 6、事务的隔离级别?
- 7、drop、truncate、delete的区别?
- 8、MySQL 为什么 InnoDB 是默认引擎?
- 9、MySQL聚簇索引与非聚簇索引的区别(InnoDB 与 Myisam 引 擎)?
- 10、MySQL 索引底层结构为什么使用 B+树?
1、了解SQL的执行顺序吗?
SQL语句的执行顺序如下:
- FROM子句:确定数据来源,包括JOIN的表。
- ON:执行JOIN条件。
- JOIN:如果有JOIN,根据JOIN类型(如INNER、LEFT),将两个表进行合并。
- WHERE子句:过滤记录。
- GROUP BY子句:根据指定的列分组记录。
- HAVING子句:过滤分组。
- SELECT子句:选取特定的列。
- DISTINCT子句:去除重复数据。
- ORDER BY子句:最后对结果进行排序。
- LIMIT子句(或者是TOP,依赖于数据库):最后的结果截取。
SELECT DISTINCT employee.name
FROM department
JOIN employee ON department.id = employee.department_id
WHERE department.name = 'Sales'
AND employee.salary > 50000
GROUP BY employee.name
HAVING COUNT(*) > 2
ORDER BY employee.name DESC
LIMIT 0, 10;
在这个例子中,首先确定数据来源是department和employee表,通过department.id和employee.department_id字段进行JOIN。然后,应用WHERE子句来过滤部门名称不是’Sales’并且薪水低于50000的员工。接着,根据employee.name进行分组,并使用HAVING子句过滤那些员工人数不超过2个的组。之后,选择employee.name列,去除重复项,最后根据employee.name降序排序结果,并限制结果集的大小为从第一条开始的共10条记录。
2、一条SQL查询非常慢,我们怎么去排查和优化?
- 确认问题
- 执行计划:使用 EXPLAIN 或 EXPLAIN ANALYZE 查看SQL查询的执行计划。这可以帮助你了解查询的执行路径,包括哪些索引被使用,是否有全表扫描,关联操作的类型等。
- 慢查询日志:检查数据库的慢查询日志,找出慢的查询和它们的执行时间。
- 统计信息:确保表的统计信息是最新的,因为查询优化器依赖于这些信息来生成最佳执行计划。
- 分析查询
- 索引使用:检查查询使用了哪些索引。如果没有使用索引或者使用了错误的索引,可能会导致查询变慢。你可以尝试增加或优化索引。
- 查询复杂度:查看查询的结构,是否有子查询、嵌套查询、联接等复杂操作。可能需要简化查询或重新设计。
- 表扫描:查看是否存在不必要的全表扫描。如果有,考虑增加适当的索引。
- 优化策略
- 添加或优化索引:如果发现某些查询可以通过索引加速,尝试为相关字段添加索引。
- 减少返回数据量:通过选择性字段、过滤条件(如 WHERE 子句)来减少查询返回的数据量。
- 分区表:对于非常大的表,可以考虑分区,这样可以加快查询速度。
- 避免SELECT *:明确选择必要的字段,而不是使用 SELECT *。
- 批量操作:如果有大量的数据处理需求,考虑将大查询分成小批量处理。
- 缓存查询结果:对于经常执行但变化不大的查询,可以考虑使用缓存来减少数据库的负载。
- 使用JOIN优化:对于关联操作,尽量使用 INNER JOIN 或者考虑使用其他高效的联接方式。
- 避免子查询,优化为多表连接查询。
- 监控和测试
- 性能监控:在数据库中设置性能监控工具,实时观察查询性能的变化。
- A/B测试:对优化后的查询进行性能测试,确认其效率是否确实有所提高。
3、对SQL慢查询会考虑哪些优化?
- 分析语句,是否加载了不必要的字段 / 数据;
- 分析SQL执行计划(EXPLAIN 查看索引信息);
- 按照可能的优化点执行表结构变更、增加索引、SQL改写(子查询改为多表连接查询)等;
- 如果表中数据量过大,考虑分表;
- 利用缓存,减少查询次数。
4、事务的4大特性(ACID)?
- 原子性(Atomicity): 要么全部成功要么全部失败。
- 一致性(Consistency): 事务执行前和事务执行后,原本和数据库一致的数据仍然一致。
- 隔离性(Isolation): 事务与事务之间互不干扰。
- 持久性(Durability): 事务一旦被提交了,那么对数据库中的数据的改变就是永久的。
5、脏读、不可重复读、幻读
- 脏读: 也叫"读未提交",顾名思义,就是某一事务A读取到了事务B未提交的数据。
- 不可重复读: 在一个事务内,多次读取同一个数据,却返回了不同的结果。实际上,这是因为在该事务间隔读取数据的期间,有其他事务对这段数据进行了修改,并且已经提交,就会发生不可重复读事故。
- 幻读: 在同一个事务中,第一次读取到结果集和第二次读取到的结果集不同。像幻觉一样所以叫幻读。
从上面可以看出脏读和不可重复读是基于数据值的错误,幻读是基于条数增加或者减少的错误。
6、事务的隔离级别?
- read uncommited(读取未提交内容): 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。读取未提交的数据,也被称之为脏读(Dirty Read)
- read committed(读取提交内容): 这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。一个事务只能看见已经提交事务所做的改变。可解决脏读。
- repeatable read(可重读): 这是MySQL的默认事务隔离级别,同一事务的多个实例在并发读取数据时,会看到同样的数据。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。可解决脏读、不可重复读。
- serializable(可串行化) : 这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。可解决脏读、不可重复读、幻读。
7、drop、truncate、delete的区别?
速度: drop > truncate > delete。
回滚: delete支持,truncate和drop不支持。
删除内容: delete表结构还在,删除部分或全部数据,不释放空间。truncate表结构还在,删除全部数据,释放空间。drop表结构和数据不在,包括索引和权限,释放空间。
8、MySQL 为什么 InnoDB 是默认引擎?
聚簇索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一 个聚簇索引,因为一个表的物理顺序只有一种情况,所以,对应的聚簇索引只能有一个。聚簇索引的叶子节点就是数据节点,既存储索引值,又在叶子节点存储行数据。 Innodb 创建表后生成的文件有: frm:创建表的语句;idb:表里面的数据+索引文件。
9、MySQL聚簇索引与非聚簇索引的区别(InnoDB 与 Myisam 引 擎)?
聚簇索引是指数据库表行中数据的物理顺序与键值的逻辑(索引)顺序相同。一个表只能有一个聚簇索引,因为一个表的物理顺序只有一种情况,所以,对应的聚簇索引只能有一个。 聚簇索引的叶子节点就是数据节点,既存储索引值,又在叶子节点存储行数据。
非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。索引命中后,需要回表查询。非聚集索引(MyISAM 引擎的底层实现)的逻辑顺序与磁盘上行的物理存储顺序不同。
10、MySQL 索引底层结构为什么使用 B+树?
- B+树的所有叶节点可以通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O;
- B 树一个节点里存的是数据,而 B+树存储的是索引(地址),所以 B 树里一个节 点存不了很多个数据,但是 B+树一个节点能存很多索引,B+树叶子节点存所有的数据。
- B+树叶子节点是一个双向链表的数据结构,便于范围查找。
对MySQL索引部分感兴趣的欢迎阅读!MySQL面试索引篇。