thinkphp站内搜索不可依赖原生like或fulltext,10万行后性能骤降;主流方案是elasticsearch(支持拼音、高亮、分布式)或轻量级manticore(mysql协议接入),严禁在控制器中手写like模糊查询。

ThinkPHP 本身不提供开箱即用的搜索引擎,站内检索必须依赖外部方案;直接用 WHERE ... LIKE 或 fulltext 在数据量超过 10 万行后基本不可用,响应会从毫秒级跳到秒级甚至超时。
MySQL FULLTEXT 索引只适合小规模、低频更新场景
MySQL 的 FULLTEXT 确实能支持中文分词(5.7+ 内置 ngram,8.0+ 支持自定义词典),但有硬伤:
- 建索引慢、锁表久,
ALTER TABLE ... ADD FULLTEXT在百万级表上可能卡住几分钟 - 更新频繁时,全文索引维护开销大,
INSERT/UPDATE延迟明显上升 - 不支持拼音搜索、模糊纠错、同义词扩展等基础搜索体验功能
-
LIKE '%关键词%'即使加了 FULLTEXT 也无效,必须用MATCH ... AGAINST语法
适用场景:后台管理系统的简单日志检索、内容少于 5 万条且几乎不更新的静态文档库。
Elasticsearch 是 ThinkPHP 站内搜的主流选择
90% 以上的中大型 ThinkPHP 项目都用 Elasticsearch(ES)替代数据库原生搜索,因为:
- 支持拼音、模糊、高亮、分页深度优化(
search_after替代OFFSET) - 写入和查询分离,不影响主库性能;数据可异步同步(用 Logstash、Canal 或自研监听)
- ThinkPHP 可通过
elasticsearch/elasticsearch官方 PHP SDK 直接调用,封装成本低 - 集群横向扩展容易,查 1000 万商品标题也能稳定在 100ms 内
注意点:think-swoole 或长连接环境下,ES 客户端实例要复用,别每次请求都 new Client;同步延迟控制在 1–3 秒内是合理预期,别强求实时。
用 Sphinx / Manticore 替代 ES 的轻量方案
如果服务器资源紧张、不想运维 Java 环境,Sphinx 及其现代分支 Manticore 是更轻的选项:
- 纯 C++ 实现,内存占用低,启动快,适合中小团队
- 支持中文分词(需配合 coreseek 或第三方分词插件)、范围查询、属性过滤
- 与 ThinkPHP 集成只需走 MySQL 协议:把 Manticore 当作一个“特殊 MySQL”来查,用
Db::query()发送SELECT * FROM idx_name WHERE MATCH('xxx') - 不支持分布式,单机承载上限约 5000 万文档,再往上就得切分或换 ES
典型配置路径:/etc/sphinx.conf 里定义 source(连主库)、index(建索引字段)、searchd(启服务),然后用 indexer --rotate 全量重建 + searchd 启动守护进程。
千万别在控制器里手写 LIKE 模糊查
这是最常踩的坑:用户一输关键词,就执行 Db::name('article')->where('title', 'like', "%{$kw}%")->select()。后果很直接:
- 哪怕加了 B+ 树索引,
%xxx%也强制全表扫描,10 万行平均耗时 > 800ms - 并发稍高(比如 20 QPS),数据库 CPU 直接打满,连带影响其他接口
- 无法做搜索相关性排序,所有结果都是无序返回
临时缓解只能加 field() 限制字段 + limit(20),但治标不治本;真要上线,必须切换到 ES 或 Manticore,没有中间路线。
搜索不是“加个 input 框 + like 就完事”,核心在于把检索逻辑从数据库卸载出去;ES 配置复杂但长期省心,Manticore 上手快但扩展性有限——选哪个,取决于你当前有没有专职运维、数据增长速度、以及能否接受 2 秒内的搜索延迟。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











