优化多语言数据库查询的关键是减少次数、合并逻辑、利用缓存与索引:用单次SQL聚合或多表JOIN替代循环查询,启用并合理配置查询缓存,预加载全量翻译后PHP映射,为(content_id, lang_code)等组合字段添加联合索引。

多语言数据库查询过多,核心问题不在“多语言”本身,而在于重复、低效的查询方式——比如为每种语言单独查一次表,或在循环中反复执行相同结构的查询。优化关键不是删语言,而是减少查询次数、合并逻辑、利用缓存和索引。
用单次查询替代多次语言查询
避免对同一内容(如菜单、文章标题)按 language_id 循环查 N 次。改用一条 SQL 一次性拉取所有语言版本:
- 在模型中使用
GROUP_CONCAT或JSON_OBJECT(MySQL 5.7+)聚合多语言字段,例如:SELECT id, GROUP_CONCAT(CONCAT(lang_code, ':', title) SEPARATOR ';') AS titles FROM content_i18n GROUP BY id - 或用 LEFT JOIN 关联主表与多语言表,指定所需语言字段:
$this->db->select('c.id, c.slug, t1.title as title_zh, t2.title as title_en, t3.title as title_ja')$this->db->join('content_translations t1', 'c.id = t1.content_id AND t1.lang_code = "zh"', 'left')$this->db->join('content_translations t2', 'c.id = t2.content_id AND t2.lang_code = "en"', 'left')
启用数据库查询缓存并设置合理过期
对不常变的多语言内容(如系统文案、静态页面标题),开启 CodeIgniter 内置查询缓存:
- 在
application/config/database.php中启用:$db['default']['cache_on'] = TRUE;$db['default']['cachedir'] = WRITEPATH . 'cache/db/'; - 在查询时显式指定缓存时间(单位:秒):
$this->db->cache_on();$this->db->cache_set_timeout(3600); // 缓存1小时$query = $this->db->get('content_translations'); - 注意:缓存目录需可写,且更新语言内容后要主动清除对应缓存(
$this->db->cache_delete('table_name'))
预加载语言数据 + PHP 层映射
对中等规模的语言集(如支持 5–10 种语言),可一次性查出全部翻译,再用 PHP 按需提取,避免每次请求都查库:
- 查询时按
content_id + lang_code作为复合键拉取全量:$this->db->select('content_id, lang_code, title, description')->from('content_translations')->where_in('lang_code', ['zh', 'en', 'ja', 'ko']); - 在控制器中组织成二维数组:
$i18n = []; foreach ($rows as $r) { $i18n[$r->content_id][$r->lang_code] = $r; } - 视图中直接用
$i18n[$id]['en']->title获取,无额外查询
添加针对性数据库索引
多语言表高频查询字段必须建联合索引,否则缓存再好也扛不住慢查询:
- 常见瓶颈字段组合:
(content_id, lang_code)—— 用于按内容 ID 查指定语言 - 若常按语言查列表:
(lang_code, content_id)—— 支持按语言分页或排序 - 避免仅对
lang_code单独建索引,效果有限;联合索引顺序很重要,等值条件字段放前面



















