ThinkPHP的like查询默认不走索引,因MySQL的B+树索引不支持左模糊(如'%abc'),必须改为前缀匹配('abc%')或改用FULLTEXT索引、ES等方案。

ThinkPHP 的 like 查询默认不走索引,不是框架的问题,而是 SQL 本身触发了 MySQL 的索引规避规则——只要写法不对,哪怕字段加了索引也白搭。
为什么 where('name', 'like', '%abc') 一定不走索引
MySQL 的 B+ 树索引依赖「最左前缀匹配」,%abc 是左模糊,无法从索引树根节点开始比对,数据库只能放弃索引、全表扫描。你用 EXPLAIN 看执行计划,type 会是 ALL,key 是 NULL。
常见错误现象:
- 明明给
name字段加了索引,where('name', 'like', '%关键词')还是慢得像卡住 -
buildSql()输出的 SQL 看着正常,但EXPLAIN一跑发现没走索引 - 用
getLastSql()拿到带值的 SQL 后,手动在 MySQL 客户端执行EXPLAIN,才暴露问题
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 能改成前缀匹配就立刻改:
where('name', 'like', 'abc%')—— 这个可以走索引 - 用户输入不可控时,别硬撑,前端加提示:“支持以关键词开头的搜索”
- 绝对避免在生产环境写
whereRaw("name LIKE '%{$keyword}%')",这是性能炸弹
where('name|mobile', 'like', '%abc%') 多字段 OR 模糊查询的坑
ThinkPHP 支持用 | 分隔多个字段做 OR 模糊查询,语法简洁,但底层生成的是 name LIKE '%abc%' OR mobile LIKE '%abc%' —— 两个左模糊,索引全部失效。
使用场景:后台订单搜索页,要同时在订单号、买家昵称、手机号里搜关键词。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 如果字段都有索引,且业务允许前缀查,统一转成
name LIKE 'abc%' OR mobile LIKE 'abc%' - 若必须支持任意位置匹配,别靠多个
LIKE硬扛,直接上FULLTEXT索引 +MATCH ... AGAINST - 不要在分页列表里无限制地
OR五六个字段,字段越多,全表扫描越重,内存和 IO 压力越大
什么时候该换 FULLTEXT 而不是死磕 LIKE
当你的模糊查询本质是「语义检索」(比如搜文章标题、商品描述、客服工单内容),而不是精确字段匹配,LIKE 就不是合适工具。它不支持分词、权重、停用词,还容易拖垮主库。
参数差异:
-
LIKE:只做字符串通配,索引仅对前缀有效,最小匹配单位是整字段 -
FULLTEXT:按词切分(默认最小长度 4),支持自然语言模式、布尔模式;建索引要显式声明:ALTER TABLE article ADD FULLTEXT(title, content)
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先确认字段是否适合全文索引:文本长度 > 100 字、更新不频繁、搜索词多为中文/英文单词
- ThinkPHP 中改写查询:
whereRaw("MATCH(title, content) AGAINST(? IN NATURAL LANGUAGE MODE)", [$keyword]) - 注意:MySQL 默认不支持单字或短词搜索,需调
ft_min_word_len并重启服务,线上改前务必测试
预处理 + 缓存 + 限流,三招补 LIKE 的短板
就算索引和 SQL 都对了,高频模糊查询仍可能打满数据库连接或拖慢响应。这时候优化不能只盯 SQL,得看整个链路。
性能影响点:
- 用户每输一个字就发一次请求 → 瞬间几十个
LIKE并发 → 连接池打满 - 同一个热搜词反复查 → 每次都扫表 → CPU 和磁盘 IO 白耗
- 没设
LIMIT→ 查出 5 万条再 PHP 截取前 20 条 → 数据库早卡死了
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 前端加防抖(debounce),搜索框至少停顿 300ms 再发请求
- Redis 缓存高频词结果:
$redis->setex('search:苹果手机', 3600, json_encode($result)) - 后端强制加
limit(50),永远不让数据库返回超过 50 条,宁可前端提示“结果太多,请细化关键词”
真正难的不是写出能跑的 like,而是判断什么时候不该用 like——比如搜“iPhone 15”,用户其实想要的是商品,不是字符串;这时候 ES 或 MeiliSearch 才是正解,MySQL 只该管订单状态、库存扣减这些确定性操作。



















