Python 后端基础(六):MySQL 索引、事务和 SQL 优化-----数据库核心
MySQL 面试高频点通常集中在索引、事务、隔离级别、慢查询和 SQL 优化。本文用后端项目场景讲清这些知识点,不只背概念,而是知道项目里怎么用。
【一、为什么索引很重要】
索引可以理解成书的目录。
没有目录时,要找某一章只能从第一页翻到最后一页;有目录时,可以直接定位。
数据库也是一样。没有索引时,MySQL 可能要全表扫描;有合适索引时,可以快速定位数据。
例如按邮箱查用户:
sql:
SELECT id, username FROM users WHERE email = 'a@test.com';
如果 `email` 没有索引,用户表很大时查询会慢。可以加:
sql:
CREATE UNIQUE INDEX idx_users_email ON users(email);
【二、索引不是越多越好】
索引能加快查询,但会增加写入成本。
因为每次插入、更新、删除数据时,MySQL 不仅要改表数据,还要维护索引结构。
所以索引适合加在:
- 经常用于 WHERE 查询的字段
- 经常用于 JOIN 的字段
- 经常用于 ORDER BY 的字段
- 唯一约束字段,比如 email
- 高区分度字段,比如 user_id、order_no
不适合滥加在:
- 区分度很低的字段,比如 gender、is_deleted
- 很少查询的字段
- 频繁更新且查询很少的字段
【三、联合索引和最左前缀】
联合索引是多个字段一起建立索引。
sql:
CREATE INDEX idx_orders_user_status_created
ON orders(user_id, status, created_at);
这个索引适合:
sql:
WHERE user_id = ?
WHERE user_id = ? AND status = ?
WHERE user_id = ? AND status = ? ORDER BY created_at
但不一定适合:
sql:
WHERE status = ?
因为联合索引遵循最左前缀原则。简单说,索引从左到右生效,跳过左边字段可能用不上。
【四、EXPLAIN 怎么看】
"EXPLAIN” 用来查看 SQL 执行计划。
sql:
EXPLAIN SELECT * FROM orders WHERE user_id = 10;
初学者重点看:
- `type`:访问类型,ALL 通常表示全表扫描。
- `key`:实际使用了哪个索引。
- `rows`:预估扫描多少行。
- `Extra`:是否出现 Using filesort、Using temporary。
如果 `key` 是 NULL,可能说明没有用到索引。
【五、事务是什么】
事务用于保证一组操作要么全部成功,要么全部失败。
比如创建订单:
1. 创建订单
2. 扣减库存
3. 创建支付记录
如果扣库存失败,订单也应该回滚,否则会出现“订单创建了但库存没扣”的脏数据。
SQL 示例:
sql:
START TRANSACTION;
INSERT INTO orders (...);
UPDATE products SET stock = stock - 1 WHERE id = 100 AND stock > 0;
INSERT INTO payment_records (...);
COMMIT;
出错时:
sql:
ROLLBACK;
【六、ACID 怎么理解】
ACID 是事务的四个特性。
- 原子性 Atomicity:一组操作要么全成功,要么全失败。
- 一致性 Consistency:事务前后数据必须满足业务规则。
- 隔离性 Isolation:并发事务之间不能互相乱影响。
- 持久性 Durability:提交后的数据不能丢。
不用背得很玄。记住一句:事务就是为了让多步写入在异常和并发情况下仍然可靠。
【七、隔离级别和常见并发问题】
并发事务可能产生:
- 脏读:读到别人还没提交的数据。
- 不可重复读:同一事务内两次读同一行,结果不一样。
- 幻读:同一事务内两次范围查询,行数不一样。
MySQL InnoDB 默认隔离级别通常是 Repeatable Read。
面试不一定要展开源码,但要能说清:隔离级别越高,并发问题越少,但性能和并发能力可能下降。
【八、常见 SQL 优化思路】
1. 只查需要的字段,避免 `SELECT *`。
2. 给高频查询条件加合适索引。
3. 使用 `EXPLAIN` 分析执行计划。
4. 分页深时避免简单 `LIMIT 100000, 20`。
5. 避免在索引字段上使用函数。
6. 小表驱动大表,注意 JOIN 条件。
7. 批量写入减少多次网络往返。
错误示例:
sql:
SELECT * FROM users WHERE DATE(created_at) = '2026-06-01';
可能导致索引失效。可以改成:
sql:
SELECT id, username
FROM users
WHERE created_at >= '2026-06-01'
AND created_at < '2026-06-02';
【九、慢查询怎么处理】
项目中遇到慢查询,一般流程:
定位慢 SQL
-> EXPLAIN 看执行计划
-> 判断是否缺索引或索引失效
-> 调整 SQL 或索引
-> 压测或观察线上指标
不要一上来就“加缓存”。缓存是手段,不是逃避 SQL 问题的借口。
更多推荐
所有评论(0)