1.mysql的explain有什么作用?

“EXPLAIN 是 MySQL 提供的一个执行计划分析工具。它能模拟优化器执行 SQL 语句,告诉我们 MySQL 到底会怎么执行这条 SQL,从而帮助我们分析性能瓶颈。
在面试或工作中,我查看 EXPLAIN 结果时,主要关注三个最核心的字段:
1. type(访问类型 —— 决定快慢的关键) 这是判断查询性能最重要的指标。它的效率从高到低依次是:
-
system>const(主键/唯一索引精确匹配) >eq_ref>ref(普通索引) >range(范围索引) >index>ALL(全表扫描)。 -
合格标准:通常我们要求至少达到
range级别,最好是ref。如果看到ALL,说明走了全表扫描,必须优化(除非表非常小)。
2. key(实际使用的索引)
-
它告诉我们 MySQL 实际 选择了哪个索引。
-
如果显示
NULL,说明没走索引(或者索引失效了),这时就要检查是不是违背了‘最左匹配原则’,或者字段做了函数运算。 -
补充:配合
key_len可以计算出联合索引到底被用到了哪几列。
3. Extra(额外信息 —— 这里的‘坑’最多) 这里能看到很多底层细节,我最关注这几个状态:
-
Using filesort(最差):说明 MySQL 需要在内存或磁盘中进行额外的排序,而不是利用索引顺序。这是必须优化的。 -
Using temporary(很差):说明用到了临时表(常用于GROUP BY或DISTINCT),性能损耗大。 -
Using index(最好):说明触发了覆盖索引(Covering Index),不需要回表,性能非常高。
总结: EXPLAIN 就像是 SQL 的 X 光机。我通常用它来定点清除项目中的慢查询,主要目标是:消除 ALL(全表扫描),避免 filesort(文件排序),并尽量实现 Using index(覆盖索引)。”
2.怎么查看是否有走索引?
同上
3.怎么查看表的索引?
“在日常开发和排查问题时,我主要使用两种方式来查看索引:
1. 最常用的命令:SHOW INDEX
-
命令:
SHOW INDEX FROM 表名;(或者SHOW KEYS FROM 表名;,效果一样)。 -
核心关注点(不只是看有没有,还要看细节):
-
Non_unique:如果是 0,说明是唯一索引(或主键);如果是 1,说明是普通索引。 -
Seq_in_index:这对于联合索引非常重要,它显示了字段在索引中的顺序,帮助我判断是否符合‘最左匹配原则’。 -
Cardinality(基数):这是一个估算值,代表索引中不重复值的数量。这个值越高,说明索引区分度越好,查询效率通常越高。如果这个值很低,可能需要考虑优化索引。
-
2. 最直观的方式:SHOW CREATE TABLE
-
命令:
SHOW CREATE TABLE 表名; -
场景:这个命令会打印出创建表的完整 DDL 语句。
-
优点:对于复杂的联合索引或者要查看索引的具体类型(如
USING BTREE),直接看 DDL 往往比看列表更清晰,而且可以直接复制出来用于在测试库复现结构。
3. 批量查询(运维视角):information_schema
- 如果我需要写脚本统计整个数据库的索引情况,我会查询
information_schema.STATISTICS表,这样可以进行更复杂的 SQL 筛选。”
4.给你张表,发现查询速度很慢,你有那些解决方案
总结: 优化的优先级是:索引 > SQL 改写 > 缓存 > 分库分表。绝大多数情况下,一个合理的索引就能解决问题。”
“这是一个非常经典的生产环境调优问题。我通常会按照**‘先诊断,后调优,最后动架构’**的思路,分三步走:
第一步:诊断与定位(不盲目瞎猜)
-
开启慢查询日志 (Slow Query Log):首先抓到是哪条 SQL 慢。
-
分析执行计划 (EXPLAIN):对慢 SQL 执行
EXPLAIN,重点看type是否走了全表扫描(ALL),以及key是否用到了预期的索引,Extra有没有出现Using filesort或Using temporary。
第二步:SQL 与索引优化(低成本,高收益) 这是解决 80% 问题的阶段:
-
索引调优:
-
补索引:给
WHERE、ORDER BY、GROUP BY和JOIN的关联字段加上索引。 -
遵循最左匹配:如果是联合索引,确保查询条件满足最左匹配原则。
-
覆盖索引:尽量只查询需要的字段(避免
SELECT *),让查询直接在索引树上完成,避免回表。
-
-
SQL 改写:
-
避免索引失效:检查有没有在索引列上做计算、函数操作,或者使用了
!=、LIKE '%xx'(左模糊)。 -
优化连表:
JOIN查询时,确保小表驱动大表,且被驱动表的连接字段一定要有索引。 -
优化深分页:针对
LIMIT 1000000, 10这种深分页,利用子查询 ID 或 标签记录法(where id > last_id)来替代。
-
第三步:架构与表结构优化(高成本,最后手段) 如果 SQL 已经优化到极致,但数据量确实太大(比如单表过亿),才考虑这层:
-
引入缓存 (Redis):对于读多写少的热点数据,利用 Redis 抗压。
-
冷热分离:将历史归档数据移到冷库,主表只留最近的数据。
-
分库分表:
-
垂直拆分:把大字段(如 Text/Blob)拆到另一张附表中。
-
水平拆分:如果单表超过 2000 万行且性能明显下降,考虑 Sharding(分库分表)。
-
5.如果Explain用到的索引不正确的话,有什么办法干预吗?
-
FORCE INDEX(强推 - 最常用):-
用法:
SELECT * FROM table FORCE INDEX (idx_a) ... -
作用:强制 MySQL 只从这个索引和全表扫描中选一个(基本就会选这个索引)。这是最强硬的干预。
-
-
IGNORE INDEX(屏蔽):-
用法:
SELECT * FROM table IGNORE INDEX (idx_wrong) ... -
作用:如果你发现 MySQL 总是傻傻地去走一个效率极低的索引,你可以显式地‘禁用’它,逼优化器去选别的。
-
-
USE INDEX(建议):- 这只是给优化器一个‘建议’,MySQL 还是有可能不听你的。