如何在CodeIgniter中批量查询多ID数据并展示分组结果
优化CodeIgniter模型的N+1查询问题
你的问题是典型的N+1查询性能问题——先查一次table0得到N条数据,然后循环每条数据查一次table1,导致额外N次数据库请求。咱们可以通过批量查询+结果映射的方式,把查询次数降到2次,同时完全兼容原有视图的展示逻辑。
重构后的模型函数
替换你原来的get_quick_navi_menu函数,代码如下:
function get_quick_navi_menu($q_code) { // 第一步:查询table0的基础数据 $this->db->select("*"); $this->db->where('q_id', $q_code); $this->db->from("table0"); $q = $this->db->get(); $final = array(); if ($q->num_rows() > 0) { $table0_rows = $q->result(); // 提取所有需要查询的table1的id,组成数组 $table1_ids = array_column($table0_rows, 'id'); // 第二步:批量查询table1的所有匹配数据 $this->db->select("*"); $this->db->from("table1"); $this->db->where_in("id", $table1_ids); // 使用where_in替代循环的where $table1_q = $this->db->get(); // 把table1的结果按id分组,方便后续快速匹配 $table1_groups = array(); if ($table1_q->num_rows() > 0) { foreach ($table1_q->result() as $t1_row) { if (!isset($table1_groups[$t1_row->id])) { $table1_groups[$t1_row->id] = array(); } $table1_groups[$t1_row->id][] = $t1_row; } } // 第三步:把table1的结果映射到对应的table0行上 foreach ($table0_rows as $row) { // 如果当前table0的id有对应的table1数据,赋值给children if (isset($table1_groups[$row->id])) { $row->children = $table1_groups[$row->id]; } array_push($final, $row); } } return $final; }
优化说明
查询次数从N+1降到2次:
- 第一次查询
table0获取所有符合条件的行 - 第二次用
WHERE IN批量查询table1,只会生成一条类似这样的SQL:SELECT * FROM `table1` WHERE `id` IN ('17','20','21','22','23')
- 第一次查询
结果映射保持原有结构:
通过array_column提取id数组,再把table1的结果按id分组,最后遍历table0的行时直接匹配对应分组,这样生成的$final数组结构和你原来的完全一致,视图代码不需要做任何修改,直接就能正常展示分组结果。性能提升明显:
当table0返回的行数越多,优化效果越显著——减少了数据库连接开销和重复查询的资源消耗。
验证效果
你可以在模型里添加echo $this->db->last_query();在$table1_q = $this->db->get();之后,就能看到生成的批量查询SQL,确认是你想要的IN形式。
内容的提问来源于stack exchange,提问作者Dingo Ghatr
相关产品推荐
相关产品推荐

