1. 核心查询与理想索引
- 目标 SQL :
SELECT ... FROM 表 WHERE 字段0 = 0 AND fail IS NULL; - 理想索引方案 :建立联合索引
(字段0, fail)。因为在 MySQL 索引中,IS NULL被视作一个特定的等值,联合索引可以完美匹配这两个查询条件。
2. 实际操作中遇到的障碍(报错 1167)
- 报错信息 :
1167 - The used storage engine can't index column 'fail' - 根本原因 :
fail字段的数据类型是TEXT。MySQL 不允许对TEXT或BLOB类型的字段创建完整索引,必须指定索引前缀长度。
3. 两种解决方案对比
| 方案 | 具体操作 | 优点 | 缺点 / 注意事项 |
|---|---|---|---|
| 方案一(强烈推荐) | 修改 fail 字段类型为 TINYINT 或 INT (业务上通常表示布尔状态或计数),然后正常创建联合索引 (字段0, fail)。 |
性能最佳 :索引体积小、查询极快;符合数据库设计规范,避免滥用 TEXT。 |
修改大表字段类型会锁表,需在业务低峰期执行。 |
| 方案二(兜底方案) | 保留 TEXT 类型,创建前缀索引 :(字段0, fail(100))。 |
无需改动表结构,能快速解决报错。 | 索引体积大、性能不如方案一;无法实现"覆盖索引"(需回表)。注意前缀长度需小于 767 字节(如 utf8mb4 下建议不超过 191)。 |
4. 最终结论与建议
- 如果业务允许,请务必采用方案一 (改字段类型)。用
TEXT存状态值属于设计失误,改掉它才是治本之策,后续所有相关查询都能受益。 - 如果因特殊原因无法改表,采用方案二(前缀索引)作为临时或兜底措施,需接受其性能折损。
- 操作完成后,务必用
EXPLAIN验证,确保执行计划的key列显示为新索引,且type为ref或range。