答案:创建高效索引需优先为高选择性列和查询高频字段建索引,善用复合索引并遵循最左前缀原则,避免低基数列单独索引,合理使用前缀索引与覆盖索引,杜绝在索引列上使用函数或表达式导致失效。
在mysql中创建高效索引的关键在于理解查询模式、数据分布和索引机制。合理的索引能显著提升查询性能,但不当使用会增加写入开销并浪费存储空间。以下是构建高效索引的核心策略。
选择合适的列创建索引
并不是所有列都适合加索引。应优先为经常出现在WHERE、JOIN、ORDER BY和GROUP BY子句中的列建立索引。
- 高选择性列优先:选择性是指唯一值数量与总行数的比值。比如用户表中的“手机号”比“性别”更适合建索引,因为前者区分度更高。
- 避免对低基数列单独建索引:如状态字段(0/1)这类只有少数取值的列,单独建索引效果差。
- 考虑前缀索引:对于较长的字符串字段(如VARCHAR(255)),可只索引前N个字符,减少索引大小。例如:CREATE INDEX idx_email ON users(email(8)); 但需确保前缀仍具备足够选择性。
善用复合索引(联合索引)
多个单列索引在多数情况下不如一个设计良好的复合索引有效。mysql使用最左前缀原则匹配复合索引。
- 遵循最左匹配原则:如果索引是(A, B, C),查询条件必须包含A才能命中索引,仅用B或C无法命中。
- 将筛选性强的列放在前面:例如在(status, created_at)中,若status只有两种值,则即使created_at范围过滤更精准,也可能导致索引效率低下。应根据实际数据分布调整顺序。
- 覆盖索引减少回表:当索引包含查询所需的所有字段时,无需再访问主表数据行。例如有索引(user_id, name, age),执行select name, age FROM users WHERE user_id = 100; 可直接从索引获取结果。
避免索引失效的常见写法
即使建立了索引,错误的SQL写法也会导致索引无法使用。
- 不在索引列上做函数操作:如WHERE YEAR(created_at) = 2024会导致全表扫描,应改为WHERE created_at >= ‘2024-01-01′ AND created_at 2025-01-01’。
- 避免隐式类型转换:比如字段是VARCHAR类型,却用数字比较WHERE mobile = 13800138000,可能引发类型转换导致索引失效。
- 少用%开头的LIKE:LIKE ‘%abc’无法利用索引,而LIKE ‘abc%’可以。
- 谨慎使用OR连接条件:除非OR两边都有独立索引且能合并,否则容易导致全表扫描。
定期维护和监控索引使用情况
索引不是一劳永逸的,需要结合实际运行情况进行优化。
- 查看执行计划:使用EXPLAIN分析SQL是否命中预期索引,关注type、key、rows和Extra字段。
- 识别未使用的索引:通过information_schema.STATISTICS或性能模式查看哪些索引长期未被使用,及时清理。
- 注意索引维护成本:每新增一条索引都会影响INSERT、UPDATE、delete的速度,尤其是大表。不要盲目添加索引。
- 考虑使用索引下推(ICP):MySQL 5.6+支持在存储引擎层过滤数据,减少回表次数,合理设计索引可充分利用该特性。
基本上就这些。高效索引的核心是“按需设计、持续观察”。结合业务查询特点,避免过度索引,同时借助工具验证效果,才能真正发挥索引的价值。