CodeIgniter查询慢主因是缓存配置错误、索引缺失或count_all_results()与get()连用导致表名重复;需设绝对缓存路径并手动开关、建复合索引、显式调用from()、避免LIKE全文搜索、及时清理缓存。

CodeIgniter 的数据库查询慢,八成不是框架本身的问题,而是缓存没开对、索引没建好、或者 count_all_results() 和 get() 连用触发了表名重复——这些地方一踩就卡,但改起来很快。
缓存目录路径和开关必须手动配齐才生效
CodeIgniter 的数据库缓存不会自动启动,cache_on() 调用前漏掉任一环节,缓存就等于没开:
-
$db['default']['cachedir']必须设为绝对路径,比如APPPATH.'cache/database/';用'cache/'这种相对路径,99% 情况下目录根本找不到 - 确认 Web 用户(如
www-data)对缓存目录有写权限:chmod 775 APPPATH.'cache/database/',755不够 - 别在
database.php里全局设'cache_on' => TRUE:所有SELECT都被缓存,后台改完数据刷不出来,第一反应就是“系统坏了” - 只在明确需要的控制器方法里调用
$this->db->cache_on(),查完立刻$this->db->cache_off(),避免污染后续查询
复合索引比单字段索引更管用
WHERE + ORDER BY 组合查询(比如按分类查最新10条文章)不加复合索引,很容易全表扫描:
- 不要给
category_id和publish_date各建一个单列索引;要建一个INDEX idx_articles_category_date ON articles(category_id, publish_date DESC) - 索引字段顺序很重要:等值条件(
=、IN)放前面,范围/排序字段(>、ORDER BY)放后面 - 用
EXPLAIN验证是否命中索引:EXPLAIN SELECT * FROM articles WHERE category_id = 5 ORDER BY publish_date DESC LIMIT 10 - IonAuth 登录查
email或username,这两个字段必须单独建UNIQUE索引,否则用户量一过万,登录就明显变慢
count_all_results() 和 get() 别传表名参数
直接连用 count_all_results('table') 和 get('table') 会触发 MySQL 报错 Not unique table/alias,因为两者内部都调了 from():
- 先显式调一次
$this->db->from('users'),之后所有操作复用这个主表 -
count_all_results(false)第二个参数设为false,防止重置查询结构 -
get()调用时完全不传表名参数,让它沿用已设的from - 如果用了
join(),确保join()的表别名不和主表名冲突,比如主表是users,别把关联表也 alias 成users
全文搜索不能靠 like(),得手建 FULLTEXT + 原生 query
$this->db->like() 是模糊匹配,数据一过万就卡;MySQL 全文索引必须手动建、手动查:
- 建索引只能用原生 SQL:
ALTER TABLE articles ADD FULLTEXT(title, content),$this->db不提供封装 - 查询必须绕过 QueryBuilder:
$this->db->query("SELECT * FROM articles WHERE MATCH(title, content) AGAINST(? IN NATURAL LANGUAGE MODE)", ['CodeIgniter']) - 中文不支持直接用 InnoDB 全文索引——它不分词,“PHP教程”会被当一个词搜,搜“教程”就匹配不到;要么预处理分词入库,要么换 Elasticsearch
- 别混用:
WHERE MATCH() AGAINST() AND title LIKE '%xxx%'会让全文索引失效,优化器直接退化成全表扫描
最常被忽略的是缓存清理:增删改后不调 $this->db->cache_delete_all() 或 $this->db->cache_delete('controller', 'method'),缓存文件就永远 stale,你看到的数据不是最新的,而是几天前的。这不是 bug,是设计如此。


















