codeigniter 不支持 mysql 全文索引自动创建与 match against 查询封装,须手动建 fulltext 索引并用原生 sql 调用;中文需分词预处理或换用 elasticsearch。

CodeIgniter 本身不提供 MySQL 全文索引的自动创建或管理能力,必须手动建索引 + 手写 MATCH AGAINST 查询,否则 like() 永远只是模糊扫描,数据一过万就明显卡顿。
MySQL 全文索引必须手动在表上创建
CodeIgniter 的查询构建器($this->db)不支持 CREATE FULLTEXT INDEX 语句的封装。你不能靠 $this->db->like() 或其他链式方法“触发”全文索引生效——它压根不走全文索引路径。
- 必须用原生 SQL 在数据库中显式创建:
ALTER TABLE articles ADD FULLTEXT(title, content);
- 字段必须是
CHAR、VARCHAR或TEXT类型,且使用utf8mb4字符集(中文需额外处理) - InnoDB 表只允许一个全文索引(不是每列一个),多字段要合并在同一
FULLTEXT定义里 - 创建后不会自动生效于旧数据:InnoDB 全文索引有延迟更新机制,新插入/更新的数据可能几秒后才可被搜到
在 CodeIgniter 中正确调用 MATCH AGAINST
一旦索引建好,就得绕过查询构建器,直接用 $this->db->query() 写原生 SQL,因为 match()、against() 不是 CodeIgniter 的方法。
- 基本用法示例:
$sql = "SELECT *, MATCH(title, content) AGAINST(? IN NATURAL LANGUAGE MODE) AS score FROM articles WHERE MATCH(title, content) AGAINST(? IN NATURAL LANGUAGE MODE) ORDER BY score DESC"; $query = $this->db->query($sql, array('CodeIgniter', 'CodeIgniter')); - 注意参数占位符
?要传两次:一次用于SELECT子句计算相关度,一次用于WHERE过滤 - 模式选择很关键:
NATURAL LANGUAGE MODE(默认)、BOOLEAN MODE(支持+、-、*等操作符)、QUERY EXPANSION MODE(自动扩展关键词) - 别用
LIKE和全文索引混用:WHERE MATCH(...) AGAINST(...) AND title LIKE '%xxx%'会导致全文索引失效,优化器会退化为全表扫描
中文搜索必须额外处理,InnoDB 原生不支持
MySQL InnoDB 的全文索引对中文分词无内置支持——它把整串汉字当一个“词”,比如“CodeIgniter教程”会被当作单个 token,无法拆出“教程”或“CodeIgniter”独立匹配。
- 官方文档明确说明:不支持无空白分隔的语言(如中文、日文、韩文)
- 免费版 MongoDB 同样不支持中文全文索引,和 MySQL 是同类限制
- 可行方案只有两个:
– 用第三方分词服务(如结巴分词)预处理文本,把分词结果存入额外字段再建全文索引
– 改用 Elasticsearch / Solr,它们自带中文分词器(ik、jieba、smartcn) - 硬上
LIKE '%关键词%'查中文?千万级数据下,EXPLAIN显示type: ALL,等于放弃索引
性能对比和上线前必验点
全文索引不是“加了就快”,用错场景反而更慢。上线前至少验证三件事:
- 执行
EXPLAIN SELECT ... MATCH ... AGAINST ...,确认key列显示你建的全文索引名,且type是fulltext - 查
information_schema.INNODB_FT_INDEX_TABLE确认索引已实际收录词条(尤其检查是否有大量停用词被过滤) - 禁用查询缓存(
$this->db->cache_off()),避免缓存掩盖真实执行耗时 - 如果搜索返回空但你知道数据存在,先检查:是否用了
IN BOOLEAN MODE却漏写+;是否关键词长度 ft_min_word_len=4);是否字段值全是空格或换行符
最常被忽略的是:全文索引只加速检索,不加速排序。ORDER BY score DESC 仍需文件排序(Extra: Using filesort),数据量大时这个步骤本身就会成为瓶颈。











