SELECT id FROM orders WHERE create_time >= '2026-03-01 00:00:00' AND create_time < '2026-03-02 00:00:00';
订单列表按日期筛,SQL 写的是 DATE(create_time) = '2026-03-01',explain 里 type 是 ALL,rows 显示 120 万。同一条 SQL 把函数去掉,rows 变成 3200。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,索引里存的是列的原始值,外面套了函数以后,每一行都要先算一遍才能比较,B+ 树没法按有序值定位。MySQL 8.0 之前没有函数索引,优化器只能退化成全表扫描。
围绕「函数包裹索引列」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。
处理上按这个顺序:把条件改成范围比较 用大于等于当天零点 和小于次日零点两个边界;确认列上是普通 btree 索引 前缀索引同样走不了这种精确范围;8.0 以上可以建函数索引 表达式要和查询里完全一致;改完把两条 SQL 的 explain 并排看 确认 type 从 ALL 变成 range。
改完只确认一件事:explain 的 type 变成 range rows 从 120 万降到 3000 上下 返回条数没有变化。
