标准答案

  1. 避免在索引列外层套函数,例如 DATE(created_at);应改为明确的时间范围条件。
  2. 字段类型与参数类型要一致,字符串与数字、不同字符集或日期格式的隐式转换可能改变比较方向并放弃索引。
  3. LIKE "%keyword" 缺少固定前缀,普通 B+ 树无法有效缩小范围;全文检索需求应使用合适的搜索索引。
  4. 对列做算术、OR 组合或非 SARGable 表达式时,要检查能否改写为可检索范围或拆分查询。
  5. 索引没有被选择也可能是选择性太差、统计信息错误或返回行过多,不能只归咎于 SQL 语法。

题目解析

所谓“索引失效”并不总是完全不用索引,更常见是索引不能把扫描范围缩小到足够小,优化器选择全表扫反而更便宜。排查时应看实际访问行数、过滤比例和执行计划,而不是只看有没有出现 key 名称。

改写 SQL 的目标是保留列的原始可排序性。例如查某一天的数据,应把日期转换到常量一侧,使用 [当天开始, 次日开始) 的范围,而不是逐行对 created_at 求日期。

常见误区

  • 把所有未命中索引的问题都用 FORCE INDEX 压过去,掩盖数据分布或查询设计问题。
  • 为了避免函数条件在应用层拉回全量数据再过滤,造成更大的网络和内存开销。

作者信息