mysql索引如何提高查询性能_mysql优化基础方法

2次阅读

索引非万能,WHERE未用索引列、函数/隐式转换、返回大量行均致失效;复合索引需最左前缀连续匹配;覆盖索引可避免回表;唯一索引重在语义与锁优化;执行计划是否真实走索引才是关键。

mysql索引如何提高查询性能_mysql优化基础方法

为什么加了索引查询还是慢

索引不是万能的,WHERE 条件没用上索引列、用了函数或类型隐式转换、或者查询返回大量行,都会让索引失效。比如写 WHERE YEAR(create_time) = 2023mysql 无法使用 create_time 上的普通 B+ 树索引;又比如 WHERE user_id = '123',而 user_idint 类型,字符串比较会触发隐式转换,导致索引跳过。

实操建议:

  • EXPLaiN 查看 type 是否为 ref/rangekey 是否显示实际使用的索引名
  • 避免在索引列上做计算、函数调用、LIKE '%xxx' 开头匹配
  • 确保查询条件的数据类型和字段定义完全一致(如 INTINT,不是 INTVARCHAR

复合索引的最左前缀怎么生效

MySQL 的复合索引(如 (a, b, c))只支持从左到右连续匹配。这意味着它可以加速 WHERE a = ?WHERE a = ? AND b = ?WHERE a = ? AND b = ? AND c = ?,但对 WHERE b = ?WHERE a = ? AND c = ?(跳过 b)无效。

实操建议:

  • 把高频等值查询字段放最左,范围查询(>BETWEEN)字段放中间,排序/分组字段放最后
  • 如果常查 statuscreated_at,但 status 只有 3 个值,而 created_at 高度离散,应建 (status, created_at) 而非反过来
  • 不要盲目字段:超过 3 列的复合索引维护成本高,且命中率未必提升

什么时候该用覆盖索引

覆盖索引指查询所需的所有字段都包含在索引中,无需回表查聚簇索引。例如表有 idnameemailstatus,而你执行 select name, email FROM users WHERE status = 'active',若存在索引 (status, name, email),就能直接从索引页拿到全部数据。

实操建议:

  • 对高频、轻量级查询(如列表页只展示几个字段),优先考虑覆盖索引减少 I/O
  • 注意索引大小:把大字段(如 TEXT、长 VARCHAR)放进索引会显著增大索引体积,得不偿失
  • EXPLAINExtra 列是否含 using index,这是覆盖索引生效的明确信号

唯一索引和普通索引选哪个

唯一索引(UNIQUE)在写入时多一次重复值校验,但对读性能几乎无影响;普通索引允许重复,写入略快。真正关键区别在于语义和锁行为:唯一索引在 INSERT ... ON DUPLICATE KEY UPDATEREPLACE INTO 场景下能精准定位冲突行,减少锁范围。

实操建议:

  • 业务上要求唯一性的字段(如 emailorder_no)必须建 UNIQUE,既是约束也是性能保障
  • 主键默认是聚簇唯一索引,不要额外建 UNIQUE(id)
  • 如果只是想加速查询,且字段天然不唯一(如 status),用普通索引即可,别强行加 UNIQUE

索引优化最易被忽略的点:不是“有没有索引”,而是“查询是否真的走到了它”。很多慢查根源不在 SQL 写法,而在统计信息过期、索引碎片、或缓冲池未预热——这些不会报错,但会让执行计划严重偏离预期。

text=ZqhQzanResources