---
# System prepended metadata

title: Laravel N+1 problem
tags: [SQL, ' Laravel']

---

## N+1問題

在 `Laravel` 中，`N+1`問題是指在嘗試從相關模型中獲取數據時，可能會出現的一種性能問題。這種情況通常會在使用`Eloquent ORM`時發生。

舉個例子，假設你有一個部落格，有兩個相關的模型：`Post`和`Comment`。每篇`Post`都有多個`Comment`。

現在，如果你想從數據庫中獲取所有文章以及其相應的評論，你可能會這樣做：

```php=
$posts = Post::all();

foreach ($posts as $post) {
    foreach ($post->comments as $comment) {
        echo $comment->content;
    }
}
```

上面的程式碼會引發 `N+1` 問題。首先，它會執行一條 `SQL` 語句以獲取所有的文章（這是**1**）。然後，對於每篇文章，它會執行另一條`SQL`語句以獲取其評論（這是**N**）。如果有`100`個文章，那麼這段程式碼將會執行`101`次`SQL`查詢，這對性能是一個重大打擊。

## 解決N+1問題

解決 `N+1` 問題的方法是使用 `Eloquent` 的 `eager loading` 特性。`eager loading`是一種事先載入相關數據的方法，以減少之後需要進行的`SQL`查詢數量。

下面是如何使用 `eager loading` 來解決我們的 `N+1` 問題：

```php=
$posts = Post::with('comments')->get();

foreach ($posts as $post) {
    foreach ($post->comments as $comment) {
        echo $comment->content;
    }
}
```

在這裡，我們使用 `with` 方法告訴 `Laravel` 我們需要在獲取文章時預加載評論。這樣，`Laravel`會首先執行一條 `SQL` 語句來獲取所有的文章，然後再執行一條`SQL`語句來獲取所有文章的評論。這將查詢數量從`101`減少到`2`，大大提高了性能。

`Laravel`的`eager loading`是解決`N+1`問題的一種有效方法。只要在撰寫查詢時多花一點心思，就可以避免不必要的性能損失。