whereBetween() 适合连续范围查询且需字段有索引,whereIn() 仅适用于少量离散值匹配;无索引时二者均全表扫描,IN 值过多需分批或临时表,EXPLAIN 是验证索引使用的唯一手段。

BETWEEN 比 IN 更适合数值/时间范围筛选,但前提是字段有索引;IN 仅适用于离散值匹配,且值越多性能越差。
whereBetween() 和 whereIn() 的底层 SQL 差异
ThinkPHP 的 whereBetween('created_at', [$start, $end]) 会生成 BETWEEN ? AND ?,MySQL 能用 B-Tree 索引快速定位区间起点和终点;而 whereIn('id', [6,7,8,9,10]) 本质是展开成 id IN (6,7,8,9,10),即使有索引,也得做多次等值查找,无法利用索引的有序性。
- 当范围连续(如时间、年龄、ID 区间)→ 优先用
whereBetween() - 当值离散且数量少(≤ 20 个)→ 可用
whereIn(),再多就该考虑分页或改用临时表 -
whereBetween()对字符串字段也有效(如whereBetween('status', ['draft', 'published'])),但要求字段有索引且字符集支持范围比较
不加索引时,whereBetween() 一样全表扫描
很多人写了 whereBetween('updated_at', ['2025-01-01', '2025-12-31']) 却发现慢,不是方法错,而是 updated_at 没建索引。MySQL 不会自动为 WHERE 字段加索引,ThinkPHP 更不会。
- 检查索引:执行
SHOW INDEX FROM user,确认updated_at在结果里 - 补索引:
ALTER TABLE user ADD INDEX idx_updated_at (updated_at) - 复合条件(如
where(['status' => 'active', 'updated_at' => ['between', $range]]))应建联合索引:ADD INDEX idx_status_updated (status, updated_at),顺序不能反 - 避免函数破坏索引:别写
where('DATE(updated_at)', '2025-01-01'),改用whereBetween('updated_at', ['2025-01-01 00:00:00', '2025-01-01 23:59:59'])
IN 查询超 500 个值时的实际对策
MySQL 默认对 IN 列表长度没硬限制,但值太多会导致解析慢、执行计划失效、甚至触发 max_allowed_packet 错误。线上常见于导出筛选或后台批量操作。
立即学习“PHP免费学习笔记(深入)”;
- 拆成多个查询,每批 ≤ 200 个 ID,用
chunk()处理:UserModel::whereIn('id', $idList)->chunk(200, function ($users) { ... }) - 改用临时表:先
INSERT INTO temp_ids SELECT UNHEX(?)批量写入,再JOIN temp_ids查询,适合 ≥ 1000 个值 - 禁用
whereIn()的字符串拼接模式:配置'parse_in_condition' => false(TP6.1+),强制走预处理,避免 SQL 注入风险和解析开销 - 注意
whereNotIn()无法用索引优化,大数据量慎用,可改写为LEFT JOIN ... IS NULL
EXPLAIN 是唯一能验证是否走索引的手段
光看 ThinkPHP 的 getLastSql() 没用,必须执行 EXPLAIN 看 type 和 key 字段。很多“以为走了索引”的查询,实际是 type: ALL 或 key: NULL。
- 在数据库配置中加
'sql_explain' => true,每条 SELECT 自动打印 EXPLAIN 结果 - 关键指标:
type应为range(BETWEEN)或ref(IN),key显示索引名,rows越小越好 - 如果
Extra出现Using filesort或Using temporary,说明排序/分组没走索引,需调整字段顺序或加覆盖索引 - 测试时关掉缓存:
Db::name('user')->cache(false)->whereBetween(...)->select(),避免缓存掩盖真实耗时
真正卡住的从来不是语法怎么写,而是索引建没建、EXPLAIN 看没看、值列表长度控没控——这三件事漏掉任何一件,whereBetween() 和 whereIn() 都只是看起来优雅的慢查询。



















