mysql是否可以创建多个索引_mysql索引设计原则

10次阅读

mysql允许一张表创建多个索引,但需权衡写性能、空间与优化器选错风险;复合索引须遵守最左前缀原则,高频查询类型决定索引策略,冗余索引应定期清理。

mysql是否可以创建多个索引_mysql索引设计原则

MySQL 支持在一张表上创建多个索引

可以,而且很常见。MySQL(包括 InnoDB 和 MyISAM)允许对同一张表创建多个单列索引、复合索引,甚至函数索引(8.0.13+),只要不违反唯一性约束或索引长度限制。

但“能建”不等于“该建”。多个索引会带来写性能下降(INSERT/UPDATE/delete 需同步更新所有相关索引)、磁盘空间占用增加,以及优化器可能选错索引的风险。

  • SHOW INDEX FROM table_name 可查看当前所有索引
  • 单列索引过多容易导致 using filesortUsing temporary,尤其在 ORDER BY + LIMIT 场景下
  • InnoDB 中,主键索引(聚簇索引)本身会影响二级索引结构——所有二级索引叶子节点都存主键值,所以主键不宜过长(如用 UUID 作主键会放大二级索引体积)

复合索引的最左前缀原则必须严格遵守

这是 MySQL 索引失效最常见的原因。只有查询条件中包含复合索引的**连续左侧字段**,才能命中该索引。

例如有索引 INDEX idx_user_status_created (user_id, status, created_at)

  • WHERE user_id = 123 AND status = 'active' —— 命中前两列
  • WHERE user_id = 123 —— 命中第一列
  • WHERE status = 'active' —— 跳过 user_id,无法使用该索引
  • WHERE user_id = 123 AND created_at > '2024-01-01' —— status 未出现在条件中,created_at 无法利用(范围查询后列失效)

注意:等值查询(=IN)可跳过中间列?不行。只有 IN 在某些版本中可能触发“index merge”,但不可依赖,且效率通常不如设计合理的复合索引。

区分高频查询类型决定索引策略

索引不是为“查得快”而建,而是为“特定 WHERE / ORDER BY / JOIN 条件”而建。不同场景需不同设计:

  • 点查为主(如用户登录):优先 UNIQUE 单列索引(如 email),或覆盖索引(select id, name FROM users WHERE email = ?INDEX idx_email_cover (email, id, name)
  • 范围 + 排序混合(如后台分页列表):把等值字段放前面,范围字段居中,排序字段放最后 —— 例如 WHERE category = ? AND created_at > ? ORDER BY updated_at DESC,适合建 INDEX (category, created_at, updated_at)
  • JOIN 关联字段:被驱动表(即 FROM 后面的表)的关联列必须有索引,否则易触发全表扫描;驱动表索引影响较小,但若用于过滤也建议加
  • jsON 字段查询(MySQL 5.7+):不能直接在 json 列建普通索引,需用虚拟列 + 索引,例如:
    ALTER TABLE orders ADD order_status VARCHAR(20) AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.status'))) STOred;
    CREATE INDEX idx_order_status ON orders(order_status);

索引冗余与监控不可忽视

上线后很多索引实际从不被使用,却持续消耗资源。MySQL 8.0 提供了 sys.schema_unused_indexes 视图辅助识别;5.7 可通过慢日志 + performance_schema 统计来推断。

  • 避免“一个字段多个单列索引”和“前缀重复的复合索引”,例如已有 INDEX (a, b),再建 INDEX (a) 就是冗余(除非 a 单独查询频次极高且 b 值分布极不均匀)
  • innodb_stats_persistent = ON(默认开启)可让统计信息更稳定,避免优化器因采样偏差误判索引价值
  • 执行 EXPLAIN format=JSON 查看是否真正用到索引、是否发生索引下推(ICP)、是否用了覆盖索引(Extra: Using index

真正难的不是“怎么建索引”,而是“删哪个索引”和“什么时候该用函数索引替代模糊前缀匹配”。这些决策必须结合真实慢查询、数据分布、QPS 变化一起看,脱离业务语义谈索引,大概率建了也白建。

text=ZqhQzanResources