mysql 创建索引 注意事项

在 MySQL 中创建索引是提升查询性能的关键手段,但不当的创建会带来资源浪费、写入性能下降甚至优化器选错索引等问题。以下是创建索引时必须注意的核心事项:


一、索引设计阶段注意事项

  1. 明确目标查询 (WHERE, JOIN, ORDER BY, GROUP BY)

    • 只为高频、关键、性能瓶颈的查询创建索引。
    • 使用 EXPLAIN 分析查询执行计划,确认是否真正需要新索引。
  2. 遵循最左前缀匹配原则 (Leftmost Prefixing)

    • 对于 组合索引 (col1, col2, col3)
      • 有效查询:col1col1 AND col2col1 AND col2 AND col3
      • 无效查询col2col3col2 AND col3(无法使用索引)。
    • 将区分度高(唯一值多)的列放在组合索引左侧
  3. 优先考虑覆盖索引 (Covering Index)

    • 让索引包含查询所需的所有字段(SELECTWHEREJOIN 列),避免回表查询。
    • 示例:查询 SELECT name, age FROM users WHERE city='北京' → 创建 INDEX (city, name, age)
  4. 控制索引数量,避免冗余

    • 单表索引不宜过多(通常 ≤5个)。每个索引占用磁盘空间,降低 INSERT/UPDATE/DELETE 速度。
    • 检查是否有功能重叠的索引:
      • 已有 INDEX(a,b),再建 INDEX(a) 是冗余的(前缀索引可复用)。
      • 用工具如 pt-duplicate-key-checker 检测冗余索引。
  5. 选择区分度高的列

    • 区分度 = COUNT(DISTINCT col) / COUNT(*)。值越接近 1,索引效果越好(如唯一ID)。
    • 避免为区分度极低的列建索引(如性别、状态标志),优化器可能直接忽略索引。

二、索引创建时的技术细节

  1. 前缀索引优化长文本

    • VARCHAR/TEXT 列,使用前缀索引节省空间:
      CREATE INDEX idx_name ON table (column(10)); -- 只索引前10字符
      
    • 关键:计算合适长度,确保区分度:
      SELECT 
        COUNT(DISTINCT LEFT(column, 10)) / COUNT(*) AS selectivity 
      FROM table;
      
  2. 为排序/分组优化索引

    • ORDER BYGROUP BY 子句的列顺序需与索引一致,且方向相同(全 ASC 或全 DESC)。
    • 示例:SELECT ... ORDER BY a DESC, b DESC → 建 INDEX(a DESC, b DESC)
  3. 谨慎处理 NULL 值

    • 索引通常不存储 NULL(除非是唯一索引)。查询 WHERE col IS NULL 可能无法使用索引。
    • 考虑用默认值(如 ''0)替代 NULL,或使用 FULLTEXT/SPATIAL 索引。
  4. 函数和表达式导致索引失效

    • 索引无法用于函数计算的列。
      失效示例WHERE YEAR(create_time) = 2023
      优化方案WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'
  5. 隐式类型转换陷阱

    • 列与查询值类型不一致时,索引失效。
      失效示例user_id 是字符串类型,但查询 WHERE user_id = 100(整数)。

三、生产环境操作注意事项

  1. 使用 Online DDL (MySQL 5.6+)

    • ALGORITHM=INPLACE, LOCK=NONE 减少锁表时间:
      CREATE INDEX idx_name ON big_table (column) 
        ALGORITHM=INPLACE, LOCK=NONE;
      
    • 注意:某些操作仍需锁表(如修改列类型、删除主键)。
  2. 避开业务高峰期

    • 大表建索引可能耗时分钟级甚至小时级,阻塞写入操作。
  3. 监控资源消耗

    • 创建过程中监控 CPU、I/O、内存使用,避免拖垮数据库。
  4. 优先在从库创建测试

    • 在从库创建索引验证效果,确认无误再操作主库。

四、创建后的维护与验证

  1. 分析索引使用情况

    • 查询 sys.schema_index_statisticsINFORMATION_SCHEMA.STATISTICS
      SELECT * FROM sys.schema_index_statistics 
      WHERE table_schema = 'your_db' AND table_name='your_table';
      
    • 删除长期未使用的索引 (index_reads=0)。
  2. 定期更新统计信息

    • 优化器依赖统计信息选择索引。大表更新后执行:
      ANALYZE TABLE your_table;
      
  3. 注意索引碎片化

    • 频繁更新的表会导致索引碎片,定期优化:
      OPTIMIZE TABLE your_table;  -- 重建表及索引
      ALTER TABLE your_table ENGINE=InnoDB; -- 仅InnoDB有效
      

常见索引失效场景总结

场景解决方案
组合索引未用最左列调整查询条件或索引顺序
对索引列使用函数/表达式重写查询,避免列参与计算
隐式类型转换确保查询值与列类型一致
OR 连接非索引列改为 UNION 或调整索引
LIKE '%value' 左模糊考虑全文索引或改用右模糊 'value%'
优化器误选索引FORCE INDEX 或更新统计信息

最佳实践总结

  1. 少而精:控制索引数量,优先组合索引覆盖高频查询。
  2. 左前缀:组合索引列顺序 = 查询条件顺序 + 区分度降序。
  3. 覆盖查询:让索引包含 SELECT 所需字段,消除回表。
  4. Online DDL:大表操作使用 ALGORITHM=INPLACE, LOCK=NONE
  5. 持续监控:定期检查索引使用率,删除无用索引。

通过精准设计索引,可让查询速度提升十倍甚至百倍,但需时刻权衡读写性能。永远基于真实查询负载和数据分布做决策,避免盲目添加索引。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值