解決數據庫N+1查詢問題

需求

數據表以下:php

department表json

|id|name|數組

user表服務器

|id|name|department_id|微服務

需求是獲得如下結構的數據:性能

[
    {
        "id":1,
        "name":"test",
        "department_id":1,
        "department":{
            "id":1,
            "name":"測試部門"
        }
    }
]

方法一:循環查詢

  1. 查詢用戶列表
  2. 循環用戶列表查詢對應的部門信息
$users = $db->query('SELECT * FROM `user`');
foreach($users as &$user) {
    $users['department'] = $db->query('SELECT * FROM `department` WHERE `id` = '.$user['department_id']);
}

該方法查詢次數爲:1+N(1次查詢列表,N次查詢部門),性能最低,不可取。測試

方法二:連表

  1. 經過連表查詢用戶和部門數據
  2. 處理返回數據
$users = $db->query('SELECT * FROM `user` INNER JOIN `department` ON `department`.`id` = `user`.`department_id`');
// 手動處理返回結果爲需求結構

該方法其實也有侷限性,若是 userdepartment 不在同一個服務器是不能夠連表的。code

方法三:1+1查詢

  1. 該方法先查詢1次用戶列表
  2. 取出列表中的部門ID組成數組
  3. 查詢步驟2中的部門
  4. 合併最終數據

代碼大體以下:it

$users = $db->query('SELECT * FROM `user`');
$departmentIds =[ ];
foreach($users as $user) {
    if(!in_array($user['department_id'], $departmentIds)) {
        $departmentIds[] = $user['department_id'];
    }
}
$departments = $db->query('SELECT * FROM `department` WHERE id in ('.join(',',$department_id).')');
$map = []; // [部門ID => 部門item]
foreach($departments as $department) {
    $map[$department['id']] = $department;
}

foreach($users as $user) {
    $user['department'] = $map[$user['department_id']] ?? null;
 }

該方法對兩個表沒有限制,在目前微服務盛行的狀況下是比較好的一種作法。class

相關文章
相關標籤/搜索