SQL 索引基础与优化教程

2次阅读

mysql不总是使用索引,因优化器基于统计信息、数据分布和查询写法动态选择执行计划;常见失效原因包括隐式类型转换、函数包裹索引列及未满足最左前缀原则。

SQL 索引基础与优化教程

为什么 WHERE 条件用了字段却没走索引

不是加了索引就一定用得上,MySQL 会根据统计信息、数据分布和查询写法动态选择执行计划。最常见的是隐式类型转换或函数包裹导致索引失效。

  • WHERE user_id = '123'user_idint)→ 触发隐式转换,索引可能失效
  • WHERE UPPER(name) = 'JOHN' → 函数作用于索引列,无法使用 name 上的普通索引
  • WHERE status IN ('active', 'pending') AND created_at > '2023-01-01' → 如果复合索引是 (created_at, status),而查询条件没覆盖最左前缀,可能只用到部分

CREATE INDEX 时要不要加 UNIQUE

加不加取决于业务语义,不是性能优化手段。唯一索引在插入/更新时多一次重复校验,但能防止脏数据,且对 select ... LIMIT 1 类查询有潜在优化(找到一条就停)。

  • 主键和业务唯一约束(如 emailorder_no)必须建 UNIQUE 索引
  • 纯查询加速用的辅助索引(如 (user_id, type))一般不用 UNIQUE,除非逻辑上天然不重复
  • 误加 UNIQUE 可能导致应用报错 Duplicate entry 'xxx' for key 'xxx',排查时容易忽略索引定义本身

联合索引字段顺序怎么排

顺序决定索引能覆盖哪些查询,核心原则是:**区分度高 + 经常用于等值查询的字段放左边,范围查询(BETWEEN>LIKE 'abc%')字段放右边,排序/分组字段尽量靠右但不破坏最左前缀**。

  • WHERE category = ? AND price > ? ORDER BY create_time DESC → 推荐索引:(category, price, create_time)
  • 如果写成 (create_time, category, price)WHERE 中没带 create_time,整个索引基本失效
  • 区分度低的字段(如 gender 只有 ‘M’/’F’)放在左边,会导致索引树大部分分支无效,浪费空间和维护开销

EXPLAIN 看到 type=ALL 就一定没索引吗

不一定。type=ALL 表示全表扫描,但原因可能是:表太小(MySQL 认为扫磁盘比走索引还快)、索引被优化器判定为“不值得用”、或者查询返回大量行(比如 SELECT * 配合无过滤条件)。

  • 先看 rows 字段:如果只有几十行,type=ALL 是正常行为
  • 检查 key 字段是否为 NULL:是才说明真没走索引;非 NULLtype=ALL,大概率是走了索引但最终回表成本高,优化器放弃
  • FORCE INDEX 强制走某索引可验证判断,但别在线上乱试——可能让查询更慢

索引不是越多越好,每多一个索引都会拖慢 INSERT/UPDATE/delete,而且 MySQL 不会自动合并多个单列索引去模拟联合索引。真正难的不是建索引,是读懂 EXPLAIN 输出里那几行看似枯燥的字段含义。

text=ZqhQzanResources