mysql为什么要建索引_mysql索引作用说明

9次阅读

索引是数据库的“目录页”,能大幅提升查询效率,但需根据查询条件和执行计划合理创建,避免滥用导致写入性能下降和优化器误判。

mysql 为什么要建索引_mysql 索引作用说明

索引就是数据库的“目录页”,不建它,查得越慢,表越大越明显

MySQL 默认不给任何字段建索引——就像一本没目录的 1000 页书,你要找“事务隔离级别”这个词,只能一页页翻。建了索引,相当于提前把关键词按顺序整理好,再附上对应页码(即数据行位置),SELECT 时直接跳转,省掉全表扫描(type: ALL)的 IO 开销。实际中,10 万行以上的表,一个没索引的 WHERE user_id = 12345 可能要扫几万行;加了索引后,通常只需 3–4 次磁盘 IO 就定位到数据。

什么时候建索引?看查询条件和执行计划,不是看“字段重不重要”

建索引不是凭感觉,而是看 EXPLAIN 输出里哪些列反复出现在 WHEREORDER BYGROUP BYJOIN 条件中。常见有效场景包括:

  • WHERE status = 'active' —— 但前提是该字段区分度高(比如 90% 是 active 就别建)
  • ORDER BY created_at DESC LIMIT 20 —— 索引能避免排序临时表
  • JOIN orders ON users.id = orders.user_id —— 关联字段必须有索引,否则驱动表每扫一行,被驱动表都全表扫一遍
  • 组合查询如 WHERE category = 'book' AND price BETWEEN 20 AND 50 —— 考虑建联合索引 (category, price),注意最左前缀原则

为什么 有时候建了索引也不走?这些操作一写就失效

索引不是建了就自动生效。MySQL 优化器会权衡成本,遇到以下情况,常直接放弃索引,退化为全表扫描:

  • 对索引列用函数:WHERE YEAR(create_time) = 2025 → 改成 WHERE create_time >= '2025-01-01' AND create_time
  • 隐式类型转换user_idVARCHAR,却写 WHERE user_id = 12345 → MySQL 自动转成数字比较,索引失效
  • 前导通配符:WHERE name LIKE '%john' → B+Tree 无法从左边开始匹配,LIKE 'john%' 才能用索引
  • OR 连接非索引字段:WHERE a = 1 OR b = 2,若只有 a 有索引,整个条件大概率不用索引
  • 索引列参与计算:WHERE score * 2 > 100 → 改成 WHERE score > 50

建索引不是免费的,写多读少的表要格外谨慎

每次 INSERTUPDATEDELETE 都要同步更新所有相关索引树,尤其在高并发写入场景下,索引越多,写延迟越明显,甚至引发锁竞争。同时:

  • 每个索引都占磁盘空间,VARCHAR(255) 字段建索引,可能比原数据还大
  • 过多索引会让优化器选错执行计划,因为要花时间评估哪个索引“更优”
  • 主键索引(聚簇索引)决定数据物理存储顺序,INNODB 表只能有一个;其他都是二级索引,查完还要回表取完整行

真正该建索引的地方,是那些被高频查询、且过滤性足够强的字段——不是所有 WHERE 都值得加,更不是所有字段都适合单独建索引。联合索引的设计、字段顺序、是否覆盖查询,才是进阶关键。

text=ZqhQzanResources