一、索引优化的三大魔鬼细节(必考知识点)
1.1 联合索引的最左匹配原则
大家注意啦!联合索引(a,b,c)的实际存储结构是:先按a排序,a相同再按b排序,b相同再按c排序。这直接导致:
- ✅ 能走索引的情况:
where a=1、where a=1 and b=2、where a=1 and b>2 - ❌ 失效场景:
where b=2、where a>1 and b=2(范围查询右侧字段失效)
(真实踩坑案例)去年调优时遇到个索引(status, create_time),但查询条件却是create_time > '2023-01-01',导致全表扫描500万数据!
1.2 索引选择困难症
当出现多个可用索引时,MySQL会根据成本自动选择。但要注意:
- 数据倾斜严重的字段(如status只有0/1),建索引可能适得其反
- 使用
force index强制走索引要慎用(不同数据量级表现可能相反)
-- 查看索引使用情况的神器
EXPLAIN
SELECT * FROM orders
WHERE user_id = 10086 AND product_type = '电子产品'
1.3 隐式类型转换陷阱
(血泪教训)当字段是varchar类型但查询用数字时:
SELECT * FROM users WHERE mobile = 13800138000 -- 全表扫描
SELECT * FROM users WHERE mobile = '13800138000' -- 走索引
这种隐式转换会导致索引失效!DBA老司机都容易中招!
二、查询优化的五个骚操作
2.1 LIMIT分页优化
当LIMIT 100000,10时,传统写法会先读取100010行再丢弃前10万行。优化方案:
-- 延迟关联法
SELECT * FROM products
INNER JOIN (
SELECT id FROM products
WHERE category='手机'
ORDER BY price DESC
LIMIT 100000,10
) AS tmp USING(id)
2.2 避免SELECT *
这条老生常谈但总有人犯!某次优化把SELECT *改为具体字段后,查询时间从2.3秒降到0.8秒。特别是:
- TEXT/BLOB大字段
- 不需要的冗余字段
2.3 EXISTS和IN的博弈
当子查询结果集大时用EXISTS,结果集小时用IN:
-- 示例:查有订单的用户
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM orders
WHERE user_id = u.id
LIMIT 1
)
三、分库分表的三大信号灯
3.1 什么情况下需要分库分表?
- 单表数据量超过500万行(不是绝对标准)
- 磁盘空间使用率超过70%
- 主从延迟经常超过5秒
3.2 分片策略选择
- 范围分片:适合有时间特征的业务(如订单按月份)
- 哈希分片:数据均匀分布但难以范围查询
- 基因法:结合业务特征的分片(如用户ID尾号)
(真实案例)某电商平台用户表按user_id%128分128个表,配合客户端分片中间件,QPS提升8倍!
四、死锁分析与避免
4.1 查看死锁日志
SHOW ENGINE INNODB STATUS;
重点关注LATEST DETECTED DEADLOCK部分
4.2 常见死锁场景
- 交叉更新顺序:线程A先更新表1再表2,线程B先更新表2再表1
- GAP锁冲突:在RR隔离级别下的范围更新
- 唯一键冲突:并发插入相同唯一键值
五、慢查询日志分析三板斧
5.1 配置慢查询日志
# my.cnf配置
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
5.2 使用mysqldumpslow分析
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
5.3 pt-query-digest神器
pt-query-digest /var/log/mysql/slow.log > slow_report.txt
六、参数调优的六个开关
6.1 连接相关
max_connections = 2000
wait_timeout = 300
6.2 缓冲池配置
innodb_buffer_pool_size = 16G # 建议物理内存的50-70%
innodb_buffer_pool_instances = 8
6.3 日志优化
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
七、真实调优案例复盘
7.1 电商订单查询优化
原始情况:查询耗时3.2秒
优化步骤:
- 添加
(user_id, status)联合索引 - 拆分订单表为热数据(近3个月)和归档表
- 引入Elasticsearch做复杂查询
结果:平均响应时间降至320ms
7.2 千万级用户表优化
问题:用户登录查询频繁超时
解决方案:
- 建立
(username,password)覆盖索引 - 字段精简:去除冗余的JSON字段
- 引入读写分离
最终效果:登录接口TP99从5s降到800ms
(敲黑板)最后强调:所有优化都要以业务场景为导向!先证明存在性能问题,再优化,切忌过度优化!下次面试被问到MySQL优化,把这几个方向展开讲,offer绝对稳了!
386

被折叠的 条评论
为什么被折叠?



