发布于2026-05-21 阅读(0)
扫一扫,手机访问
索引不是加得越多越好,而是要让每一条查询真正用得上。很多 ThinkPHP 项目查得慢,根本原因不是没建索引,而是索引建了但 SQL 写法让 MySQL 直接弃用——你得先让查询“能走索引”,再谈“走得好不好”。

where() 哪些写法会让索引失效框架链式调用看着干净,但一写错,EXPLAIN 就显示 type: ALL、key: NULL,等于白建索引。
where('name', 'like', '%abc') —— 左模糊,B+ 树没法从头匹配,必须改成 where('name', 'like', 'abc%') 或用全文索引whereRaw('DATE(create_time) = "2024-01-01"') —— 对字段做函数操作,索引失效;应改用 whereBetween('create_time', [$start, $end])where('status', 1)->where('score', '>', 80) —— 若建的是 (status, score) 联合索引,status 是等值,score 是范围,能用上;但反过来建 (score, status),score 是范围,后面 status 就失效where('user_id', $uid)->order('id desc') —— 若只有 user_id 索引,id 没索引,排序会触发 Using filesort;要提速就得建 (user_id, id)MySQL 遵循最左前缀原则,顺序错了,索引就形同虚设。别凭感觉排,按实际查询模式来。
where('category_id', 5)->where('status', 1)->where('create_time', '>=', $t),索引应为 (category_id, status, create_time);create_time 放最后,它才能参与范围筛选where('user_id', $uid)->order('created_at desc'),索引必须是 (user_id, created_at);若写成 (created_at, user_id),user_id 等值条件就无法利用索引有序性(a, b),就别再单独建 (a);MySQL 5.7+ 会自动跳过单列索引buildSql() 只输出 SQL 字符串,不告诉你执行计划;getLastSql() 才是关键——它返回参数已替换的真实 SQL,可直接丢进 MySQL 执行 EXPLAIN。
'sql_explain' => true 加到 config/database.php,TP 会自动对每个 SELECT 打印 EXPLAIN 结果$query->getLastSql() 拿完整 SQL,复制到 MySQL 客户端执行 EXPLAIN SELECT ...type(ref/range 合理,ALL 危险)、key(是否命中你建的索引名)、rows(扫描行数是否接近结果集)delete_time IS NULL 这种条件,如果 delete_time 有大量 NULL,MySQL 可能认为选择性差而放弃索引别一上来就给所有 where 字段建单列索引。索引有维护成本,优先保障高频、高筛选性的组合场景。
id 自带聚簇索引;user_id、category_id 这类外键字段,只要出现在 JOIN 或 WHERE 中,基本都要加mobile(登录)、order_sn(订单详情页)、token(会话校验),单列索引即可,效果立竿见影status 和 create_time,几乎总是成对出现,建联合索引比两个单列更省空间、更高效TEXT、JSON 字段建索引,哪怕只 WHERE 一下,也可能导致索引膨胀、查询变慢最常被忽略的一点:索引优化不是一次性动作。业务逻辑一变,原来高效的查询可能立刻退化;每次新增或修改 where 条件、order by 字段、join 表,都得重新跑一遍 EXPLAIN 看执行计划。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8