Решение за N+1 Query со Laravel Query Detector

Дали ви се случило некогаш Laravel апликацијата што ја градите „да станува сè потешка и побавна”, иако не сте додале толку многу нови функционалности? Една од најчестите причини за ова е проблемот со N+1 query. Eloquent релации кои се повикуваат повторливо затоа што сме заборавиле да примениме eager loading.

Во овој текст ќе зборуваме за Laravel Query Detector од Beyond Code, пакет кој автоматски ги детектира N+1 query-ја за време на development и ве предупредува за да знаете точно кој дел треба да се поправи.

Што е N+1 Query и зошто е проблематичен?

Едноставно кажано, N+1 query се случува кога ги земаме главните податоци со еден query, а потоа за секој запис Laravel извршува дополнителен query за истата релација.

Пример кој често останува незабележан:

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name; // предизвикува дополнителен query секој пат
}

Кодот погоре изгледа сосема нормално. Но под хауба, Laravel може да изврши огромен број дополнителни query-ја во зависност од бројот на Post записи. Ако имате 100 записи, вкупниот број query-ја може да биде 101. Ова значително ги намалува перформансите, особено кога страницата има голем сообраќај или податоците растат.

Запознајте се со Laravel Query Detector

Laravel Query Detector е пакет чија задача е да ги „набљудува” Eloquent query-јата додека апликацијата работи во development режим. Кога ќе детектира N+1 query шаблон, пакетот ве известува дека одредена релација треба да биде eager load-ирана.

Со овој пристап можете да ја поправите перформансата уште од самиот почеток, пред проблемот да стигне до production.

Повеќе информации: https://beyondco.de/docs/laravel-query-detector/installation

Инсталација на Laravel Query Detector

Процесот на инсталација е многу едноставен и се прави преку Composer како development dependency:

composer require beyondcode/laravel-query-detector --dev

По инсталацијата, пакетот автоматски се регистрира, така што не треба рачно да додавате service provider.

Бидејќи е инсталиран со --dev флагот, пакетот е активен само во development средина и е безбеден за секојдневна употреба при развој.

Како работи кога апликацијата е активна

Кога Laravel апликацијата работи со APP_DEBUG=true, Laravel Query Detector автоматски се активира.

Кога ќе отворите страница која содржи N+1 query, пакетот ќе прикаже предупредувачка нотификација во прелистувачот. Целта е едноставна, да ви сигнализира дека одредена релација се повикува повторливо и треба да се оптимизира. На овој начин не треба да погодувате или рачно да ги броите query-јата.

Пример и решение

Да речеме дека имаме страница со листа на постови и го прикажуваме името на авторот за секој пост.

Controller:

$posts = Post::all();

return view('posts.index', compact('posts'));

Blade view:

@foreach ($posts as $post)
  <p>{{ $post->author->name }}</p>
@endforeach

Ваков код е многу подложен на N+1 query проблемот.

Правилното решение е да се користи eager loading:

$posts = Post::with('author')->get();

Со овој пристап, Laravel извршува само онолку query-ја колку што се потребни на ефикасен начин, наместо многу мали повторливи query-ја.

Објавување на конфигурација (опционално)

Ако сакате да го прилагодите однесувањето на нотификациите или излезот на Laravel Query Detector, можете да ја објавите конфигурацијата:

php artisan vendor:publish --provider="BeyondCode\QueryDetector\QueryDetectorServiceProvider"

По ова ќе се појави фајлот config/querydetector.php. Преку овој фајл можете да поставите дали предупредувањата ќе се прикажуваат како alert во прелистувачот, во лог, или преку друг механизам според вашите потреби.

Заклучок

Laravel Query Detector е исклучително корисна алатка за детектирање на N+1 query проблеми уште во фазата на development. Со едноставна инсталација и автоматски механизам на работа, овој пакет помага да ја одржувате перформансата на вашата Laravel апликација без потреба од рачна проверка на query-јата.

Благодарение на директните предупредувања кога ќе се појави N+1 query, можете подисциплинирано да го користите eager loading и да бидете сигурни дека апликацијата останува брза, чиста и подготвена за production.

Стани премиум член и доби пристап до сите содржини, специјален попуст на над 2.200 производи во ИТ маркет, верификуван профил и можност за огласување на ИТ Огласник. Плус ќе го поддржиш медиумот кој го градиме цели 16 години!

basic

членство

42 ден./мес

зачлени се

1337

членство

125 ден./мес

зачлени се
* плаќањето е на годишно ниво

Доколку веќе имаш премиум членство, најави се тука.

Добивај известувања
Извести ме за
guest
1 Коментар
Најнови
Најстари Со највеќе гласови
Inline Feedbacks
View all comments
spiritBreaker
spiritBreaker
3 months ago

Да би се намалила зависноста од надворешни пакети, полесно и поедноставно преферирам користење на веќе постоечка ларавел функционалност:

if (! App::isProduction()) {
Model::preventLazyLoading();
}

Во AppServiceProvider. Нема дополнителни конфигурации, објавување итн.