지난 편에서 찾은 범인은 이런 코드였다. 주문 목록을 가져온 뒤, 주문마다 상품을 다시 조회한다.
foreach ($orders as $order) {
// 주문마다 쿼리 한 번씩: 주문 200개면 쿼리 200번
$order->items = $db->query('SELECT * FROM order_items WHERE order_id = ?', [$order->id])->fetchAll();
}IN 으로 한 번에 가져오기
$ids = array_column($orders, 'id');
$marks = implode(',', array_fill(0, count($ids), '?'));
$rows = $db->query("SELECT * FROM order_items WHERE order_id IN ($marks)", $ids)->fetchAll();
$byOrder = [];
foreach ($rows as $row) {
$byOrder[$row->order_id][] = $row;
}
foreach ($orders as $order) {
$order->items = $byOrder[$order->id] ?? [];
}결과
| 고치기 전 | 고친 뒤 | |
|---|---|---|
| 쿼리 수 (주문 200개) | 201회 | 2회 |
| 평균 응답 | 1,840ms | 210ms |
| 최대 응답 | 5,210ms | 380ms |
IN 목록이 수천 개가 넘으면 오히려 느려질 수 있습니다. 페이지 단위로 나눠 가져오세요.
코드 열 줄 남짓 바꿨을 뿐인데 체감이 완전히 달라졌다. 메일을 보내 준 사용자에게 답장을 쓰면서 가장 뿌듯했던 순간.
코드 한 줄
