面试题从互联网各个角落收集而来

如何定位慢查询?

  • 方案1
    • 开源工具
      • Arthas
    • 运维工具
      • Prometheus
      • Skywalking
  • 方案2
    • MySQL自带慢日志(mysql性能损耗)
      • 开启慢日志方法
        • /etc/my.conf
          • slow_query_log
          • long_query_time

SQL语句执行很慢,如何分析

  • 慢的原因
    • 聚合查询
    • 多表查询
    • 表数据量过大查询
    • 深度分页查询
  • 如何分析慢
    • explain, desc 命令
      • 如何分析执行结果?
        • extra 的额外优化建议
          • using where; using index 查找使用了索引,需要的数据在索引列都能找到,不需要回表查询数据
          • using index condition 查找使用了索引
        • type
          • index,all 需要优化

了解过索引吗?什么是索引?

索引(index)是帮助 MySQL 高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构(如 B+ 树),这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

  • 帮助MySQL高效获取数据的数据结构

索引的底层数据结构了解过吗?

  • 二叉搜索树
  • 红黑树
  • B树
  • B+树
    • 阶数更多,路径更短
    • 磁盘读写代价B+树更低,叶子节点才能真正存储数据
    • 便于扫库和区间查询,叶子节点是双向链表

什么是聚簇索引?什么是非聚簇索引?

  • 聚簇索引
  • 二级索引

什么是回表查询?

知道什么是覆盖索引吗?

通过该索引查询能够一次找到所有数据,且无需回表的,就是覆盖索引

MySQL超大分页怎么处理?

使用覆盖索引加上子查询

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

索引创建的原则有哪些?

  • 单表超过10万条数据且查询比较频繁的表建立索引
  • 常常作为查询条件的字段要建立索引
  • 使用区分度高的列作为索引,尽量建立唯一索引
  • 字符串类型的字段长度较长可以建立前缀索引
  • 尽量使用联合索引,减少单列索引
  • 索引列使用NOT NULL方便优化器确定哪个索引更好用于查询

什么情况下索引会失效?

  • 违反了最左前缀法则
  • 查询范围右边的列,不能使用索引
  • 索引列上进行运算操作,索引列失效
  • 字符串不加单引号,索引失效(索引类型转换导致的失效)
  • 字符串非尾部匹配,索引失效

谈一谈对SQL优化的经验

  • 表设计优化
    • 我们参考了 阿里开发手册《嵩山版》
    • 根据实际存储数值长短设计数据类型
  • 索引的优化
  • SQL语句的优化
    • select 语句务必指明字段名称
      • 为了覆盖索引
    • 尽量用 union all 代替 union
    • 避免对 where 子句中对字段进行表达式操作
    • 能用 innerjoin 就不用 left join , right join。如必须,要以小表为驱动
  • 主从复制,读写分离
  • 分库分表

事务的特性详细说一说

并发事务带来哪些问题,如何解决这些问题?MySQL的默认隔离级别是?

  • 并发事务的问题
    • 脏读
      • 读已提交
    • 不可重复读
      • 值问题
      • 可重复读
    • 幻读
      • 数量问题
      • 串行化
  • 隔离级别
    • 未提交读
    • 读已提交
    • 可重复读*
    • 串行化

undo log 和 redo log 的区别

  • 缓冲池
  • 数据页
  • redo log
    • 物理
    • 持久
  • undo log
    • 逻辑
    • 原子 一致

事务的隔离性底层是如何保证的?

  • 锁:排他锁
  • MVCC
    • 多版本并发控制
    • 依赖于
      • 隐式字段
        • DB_TRX_ID
        • DB_ROLL_PTR
        • DB_ROW_ID
      • undo log
        • 版本链
          • 版本链数据访问规则
      • readview
        • 快照读
          • Read Committed 每次 select都生成一个快照读
          • Repeatable Read 开启事务后第一个 select 语句才是快照读的地方
        • 核心字段
          • m_ids
          • min_trx_id
          • max_trx_id
          • creator_trx_id
        • RC隔离级别下,在事务中每次执行快照读时生成 ReadView

MySQL 的主从同步原理

  • 核心:二进制日志
    • BINLOG
      • DDL
      • DML 主数据库在事务提交时,变更记录写入 Binlog 从库 binlog -> 中继日志 从库 中继日志读取事件 -> 从库数据库

你们项目用过分库分表吗?

  • 什么时候分库分表
    • 单表数据量达到1000W 或者 20GB
    • 优化解决不了性能问题
    • IO、CPU瓶颈
  • 如何拆分
    • 垂直拆分
      • 垂直分库
        • 不同表拆分到不同库
        • 适用于微服务
      • 垂直分表
        • 不常用字段单独放在一张表
    • 水平拆分
      • 水平分库
        • 一个库的数据拆分到多个库中
        • 路由规则
          • 根据id节点取模
          • 按id范围路由
      • 水平分表
        • 一个表的数据拆分到多个表中
  • 新的问题
    • 分布式事务一致性问题
    • 跨节点关联查询
    • 跨节点分页、排序函数
    • 主键去重
  • 解决方案
    • 分库分表中间件
      • mycat
      • sharding-sphere

深入问题

  1. 为什么 InnoDB 主键建议自增?
  2. 为什么非自增主键会导致页分裂?
  3. 为什么 MyISAM 和 InnoDB 索引结构不同?
  4. 为什么 B+树适合磁盘而红黑树不适合?