一、基础概念
-
什么是主键(Primary Key)?
答案: 唯一标识表中每行数据的字段或字段组合,不允许 NULL 值,确保数据唯一性。 -
外键(Foreign Key)的作用是什么?
答案: 建立表间关联,确保引用完整性。外键字段值必须存在于被引用表的主键中。 -
CHAR 和 VARCHAR 的区别?
答案:- CHAR 定长,存储效率高,适合固定长度(如身份证号)。
- VARCHAR 变长,节省空间,适合长度变化大的数据(如地址)。
-
MySQL 的默认存储引擎是什么?
答案: InnoDB(MySQL 5.5+ 后默认)。 -
主键(Primary Key)与唯一键(Unique Key)的区别?
答案:- 主键唯一标识表中每行数据,不允许 NULL,一个表只能有一个主键。
- 唯一键确保列值唯一,允许 NULL,一个表可以有多个唯一键。
-
InnoDB 和 MyISAM 的区别?
答案:- 事务:InnoDB 支持事务,MyISAM 不支持。
- 锁粒度:InnoDB 支持行级锁,MyISAM 仅支持表级锁。
- 索引结构:InnoDB 主键索引为聚簇索引,数据与索引存储在一起;MyISAM 为非聚簇索引,数据与索引分离。
二、SQL 语句
-
如何查询表中不重复的记录?
答案:SELECT DISTINCT column_name FROM table;
-
LIMIT 和 OFFSET 的作用?
答案:SELECT * FROM table LIMIT 10 OFFSET 20; -- 跳过前20条,取10条
-
如何删除表中所有数据?
答案:TRUNCATE TABLE table_name; -- 快速清空,不记录日志 DELETE FROM table_name; -- 逐行删除,可回滚
-
如何优化
SELECT COUNT(*)
查询?
答案:- MyISAM 直接读取表元数据的行数统计。
- InnoDB 需遍历索引或使用近似值(如
EXPLAIN
估算)。
-
如何优化大分页查询(如
LIMIT 1000000,10
)?
答案:
使用延迟关联:SELECT * FROM users WHERE id >= (SELECT id FROM users ORDER BY id LIMIT 1000000,1) LIMIT 10;
减少回表次数。
-
LEFT JOIN、INNER JOIN 和 RIGHT JOIN 的区别?
答案:- LEFT JOIN:返回左表所有行,右表无匹配则填充 NULL。
- INNER JOIN:仅返回两表匹配的行。
- RIGHT JOIN:返回右表所有行,左表无匹配则填充 NULL。
三、索引
-
索引的优缺点?
答案:- 优点: 加速查询、唯一约束。
- 缺点: 占用空间、降低写操作速度(需维护索引)。
-
什么情况下索引会失效?
答案:- 使用
LIKE '%abc'
- 对字段进行函数操作(如
WHERE YEAR(date) = 2023
) - 类型转换(如字符串字段用数字查询)
- 使用
-
B+树索引和哈希索引的区别?
答案:- B+树: 支持范围查询、排序,适用于磁盘存储。
- 哈希索引: 精确查找快,不支持范围查询。
-
索引类型与结构
- B+树索引:InnoDB 默认,支持范围查询,叶子节点存储数据或主键。
- 哈希索引:仅 MEMORY 引擎支持,适合精确查找。
- 联合索引:遵循最左前缀原则(如
INDEX(a, b)
无法单独使用b
查询)。
-
索引失效场景
- 对字段使用函数(如
YEAR(date)
)或类型转换。 LIKE '%abc'
左模糊查询。- OR 条件未全索引、组合索引未用第一列。
- 对字段使用函数(如
-
什么是最左前缀匹配原则?
答案:
组合索引中,查询条件需从最左列开始匹配。例如索引(a,b,c)
,WHERE a=1 AND b=2
可用索引,但WHERE b=2
不可用。 -
覆盖索引是什么?如何优化查询?
答案:
索引包含查询所需的所有字段,避免回表。例如,若索引包含(age, name)
,查询SELECT name FROM users WHERE age=25
可直接通过索引获取数据。 -
分页查询优化
- 延迟关联:先查主键再关联,减少回表次数。
SELECT * FROM users WHERE id >= (SELECT id FROM users ORDER BY id LIMIT 1000000, 1) LIMIT 10;
-
为什么要用小表驱动大表?
在 MySQL 中,“小表驱动大表”是一种优化 JOIN 操作的常见策略,其核心目的是减少外层循环次数,从而降低整体查询的计算量和 I/O 开销。以下是详细解释:嵌套循环连接(Nested-Loop Join)的工作原理
MySQL 默认使用嵌套循环算法执行 JOIN 操作,流程如下:驱动表(外层表):首先被访问的表,假设有 N 行。
被驱动表(内层表):随后被访问的表,假设有 M 行。
操作步骤:
遍历驱动表的每一行。
对驱动表的每一行,遍历被驱动表的所有行(或通过索引查找匹配的行)。
若被驱动表有索引,每次内层循环的时间复杂度近似为 O(1);若无索引,则为 O(M)。
-
小表驱动大表的核心是减少外层循环次数,显著降低计算量。
-
索引是优化的前提条件,尤其是被驱动表的 JOIN 字段必须建立索引。
-
通过 EXPLAIN 分析执行计划,验证驱动表选择和索引使用是否合理。
17. mysql 索引查找数据大概需要多少次io操作?树的高度怎么算?
B+ 树索引的结构
MySQL 的索引默认使用 B+ 树结构,特点如下:
树的高度:通常为 3~4 层(极端场景可能更高)。
- 节点容量:
每个节点存储多个键值(Key)和指针(Pointer)。
假设一个页(Page)大小为 16KB,单个索引键(如 BIGINT)占 8 字节,指针占 6 字节,则:
单个节点可存储的键值数量:16KB / (8B + 6B) ≈ 1170 个。
若叶子节点存储完整数据行(聚集索引),假设每行数据 1KB,则:
单个叶子节点可存储的行数:16KB / 1KB = 16 行。
- 索引层高
层高越低,I/O 越少:
若单表数据量为 N,树高计算公式:h ≈ log(N) / log(节点容量)。
示例:
节点容量 1170,叶子节点容量 16。
3 层 B+ 树可支撑的数据量:1170 × 1170 × 16 ≈ 21,902,400 行。
4 层 B+ 树可支撑:1170^3 × 16 ≈ 25.6 亿行。
四、事务与锁
-
ACID 是什么?
答案:- 原子性(Atomicity): 事务全部成功或全部失败。
- 隔离性(Isolation): 事务间互不干扰。
- 持久性(Durability): 事务提交后数据永久保存。
- 一致性(Consistency): 数据符合约束规则。
-
事务隔离级别有哪些?
答案:- READ UNCOMMITTED(可能脏读)
- READ COMMITTED(解决脏读)
- REPEATABLE READ(MySQL 默认,解决不可重复读)
- SERIALIZABLE(完全隔离,性能低)
-
什么是死锁?如何避免?
答案: 多个事务互相等待对方释放锁。
避免方法: 按顺序访问资源、减小事务粒度、设置超时。 -
锁的类型与死锁处理
- 行级锁:InnoDB 支持,并发度高但可能死锁。
- 表级锁:MyISAM 使用,开销小但并发度低。
- 避免死锁:按顺序访问资源、设置事务超时、启用死锁检测。
-
InnoDB 如何通过 MVCC 实现可重复读?
答案:
通过隐藏的事务版本号和 Read View 实现多版本控制。事务启动时生成一致性视图,读取数据时根据版本号判断可见性。
五、性能优化
-
EXPLAIN 的作用?
答案: 分析 SQL 执行计划,查看是否使用索引、扫描行数等。 -
如何优化慢查询?
答案:- 添加索引
- 避免
SELECT *
,只查必要字段 - 分库分表
- 优化 SQL 结构(如减少子查询)
-
什么是覆盖索引?
答案: 索引包含查询所需的所有字段,无需回表查询数据行。 -
慢查询优化
- 使用
EXPLAIN
分析执行计划,关注type
(访问类型)和key
(使用索引)。 - 避免
SELECT *
、减少子查询、添加覆盖索引。
- 使用
-
分库分表策略
- 垂直分库:按业务拆分(如用户库、订单库)。
- 水平分表:按规则分散数据(如按用户 ID 哈希)。
- 分布式事务:使用 2PC、TCC 或本地消息表保障一致性。
-
备份与恢复
- mysqldump:逻辑备份,适合小数据量。
- XtraBackup:物理备份,支持热备份与增量备份。
六、高可用与架构
-
主从复制的原理及配置步骤?
答案:- 原理:主库写 Binlog,从库通过 I/O 线程读取并写入 Relay Log,SQL 线程重放日志同步数据。
- 步骤:主库开启 Binlog,从库配置主库信息并启动复制。
-
分库分表的常见方案?
答案:- 水平分表: 按数据行拆分(如按用户 ID 哈希)。
- 垂直分表: 按列拆分(将常用字段与不常用字段分开)。
七、高级特性
-
什么是窗口函数?举例说明。
答案:SELECT name, salary, RANK() OVER (ORDER BY salary DESC) AS rank FROM employees;
-
JSON 类型字段如何查询?
答案:SELECT * FROM table WHERE JSON_EXTRACT(data, '$.key') = 'value';