Laravel에서 강제로 로드하고 N+1 문제를 방지하는 방법

9123 단어 phpwebdevlaravel

소개하다.
과거 기사에서 Laravel 데이터베이스 조회에서 '불러오기 갈망' 을 사용하면 실현할 수 있는 성능 개선에 대해 토론했다.읽지 않은 사람에게click here if you want to give it a quick read.

급장이 뭐예요?
데이터베이스에서 어떤 모델을 얻은 다음에 모델의 관계를 어떤 유형으로 처리할 때 eager loading 를 사용하는 것이 중요하다.Laravel을 사용하면 데이터를 즉시 불러오는 것이 매우 간단해서 기본적으로 데이터가 N+1 문제에 부딪히는 것을 방지할 수 있다.이 문제는 데이터베이스에 대한 N+1 조회로 인해 발생한 것으로 그 중에서 N은 데이터베이스에서 추출한 항목의 수이다.이 점을 더욱 잘 설명하고 상하문을 제공하기 위해서 아래의 예를 봅시다.
만약 두 모델 ((CommentAuthor 이 있다면, 그것들 사이에는 일대일의 관계가 있다.현재 100개의 평론이 있다고 가정하면, 하나하나를 훑어보고, 저자의 이름을 출력하고 싶다.
급하게 로드하지 않으면 다음과 같은 코드가 표시될 수 있습니다.
$comments = Comment::all();

foreach ($comments as $comment ) {
    print_r($comment->author->name);
}
위의 코드는 101개의 데이터베이스 조회를 초래할 것입니다. 왜냐하면 그 결과는 '로드 지연'이기 때문입니다.첫 번째 검색은 모든 주석을 얻는 것입니다.다른 100개의 검색어는 앞으로 순환하는 모든 교체에서 저자의 이름을 얻을 것이다.분명히 이것은 성능 문제를 초래하고 응용 프로그램의 속도를 떨어뜨릴 수 있다.그렇다면, 우리는 어떻게 이 점을 개선해야 합니까?
즉각적인 로드를 사용하여 코드를 다음과 같이 변경할 수 있습니다.
$comments = Comment::with(authors)->get();

foreach ($comments as $comment ) {
    print_r($comment->author->name);
}
보시다시피, 이 코드는 보기에 거의 같지만, 여전히 읽을 수 있습니다.추가::with('authors')를 통해 모든 주석을 얻고 다른 검색을 통해 작성자를 즉시 얻을 수 있습니다.따라서 우리는 조회를 101에서 2로 줄일 것이다!
자세한 내용은 eager loading의 Laravel 문서를 참조하십시오.

Laravel에서 즉각적인 로드를 사용하는 방법
new feature Mohamed Said에 의해 추가됨) 최근에 Laravel 코드 라이브러리에 통합되어 로드 지연을 방지할 수 있습니다.이 기능은 관계가 불러오는 것을 확보하는 데 도움이 될 것이기 때문에 매우 유용하다.따라서 위의 예시와 같이 성능을 향상시키고 데이터베이스에 대한 조회량을 줄이는 데 도움을 줄 수 있다.
적재 지연을 방지하는 것은 매우 간단하다.우리는 boot()AppServiceProvider 방법에 다음과 같은 줄을 추가하기만 하면 된다.
Model::preventLazyLoading();
그래서 우리AppServiceProvider에서는 이렇게 보인다.
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // ...
        Model::preventLazyLoading();
        // ...
    }
}

프로덕션 환경에서 빠른 로드 허용
로컬 개발 환경에서만 이 기능을 사용하려고 할 수도 있습니다.이렇게 하면 새로운 기능을 구축할 때 코드에 지연된 불러오는 곳을 알릴 수 있지만, 생산 사이트를 완전히 파괴하지는 않을 것입니다.그렇기 때문에 preventLazyLoading() 방법은 부울 값을 매개 변수로 받아들이기 때문에 우리는 다음과 같은 줄을 사용할 수 있다.
Model::preventLazyLoading(! app()->isProduction());
따라서 DellAppServiceProvider에서는 다음과 같습니다.
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // ...
        Model::preventLazyLoading(! app()->isProduction());
        // ...
    }
}
이렇게 하면 APP_ENVproduction 이면, 이 기능은 지연된 불러오기 조회가 사이트에서 이상을 일으키지 않도록 비활성화됩니다.

만약 우리가 마운트 지연을 시도한다면 무슨 일이 일어날까요?
서비스 공급업체에서 이 기능을 사용하고 모델에서 로드 관계를 지연시키려면 Illuminate\Database\LazyLoadingViolationException 이상이 발생합니다.
이 점에 대한 배경 지식을 주기 위해 위의CommentAuthor 모델 예시를 사용하겠습니다.만약 우리가 이 기능을 사용한다면.
다음 코드 세그먼트에 예외가 발생합니다.
$comments = Comment::all();

foreach ($comments as $comment ) {
    print_r($comment->author->name);
}
그러나 다음 코드 세그먼트는 예외를 일으키지 않습니다.
$comments = Comment::with(authors)->get();

foreach ($comments as $comment ) {
    print_r($comment->author->name);
}

결론
개인적으로 나는 이 기능이 매우 유용할 것이라고 생각한다. 이것은 더욱 좋은 모델과 데이터베이스 조회 실천을 장려하는 데 도움이 될 것이다.나는 이것이 내가 매일 사용하는 기능이 될 것이라고 느꼈다. 나는 아마도 "그것이 없으면 내가 어떻게 생존할 것인가?"라고 생각할 것이다.
나는 네가 이 단문이 유용하다고 생각하기를 바란다.만약 네가 이런 일에 흥미가 있다면, 아래에서 나의 시사 통신을 등록할 수 있다.내가 라벨 세계에 관한 새로운 글을 보낼 때마다 너는 통지를 받을 것이다.🚀

좋은 웹페이지 즐겨찾기