Подивитися SQL одного запиту без виконання:
User::where('active', true)->orderBy('name')->toSql();
// select * from "users" where "active" = ? order by "name" asc
User::where('active', true)->toRawSql();
// select * from "users" where "active" = 1 ... - з підставленими значеннями
Вивести й продовжити чи зупинитися:
User::where('active', true)->dumpRawSql()->get(); // вивести й виконати
User::where('active', true)->ddRawSql(); // вивести й зупинити
toRawSql() зручний, щоб скопіювати запит у консоль бази й запустити EXPLAIN. Але для реального виконання Laravel завжди використовує підготовлені запити з окремими параметрами - підставлені значення лише для читання людиною.
Усі запити за запит чи команду:
DB::enableQueryLog();
// ... код ...
dump(DB::getQueryLog()); // SQL, параметри й час кожного
Слухач запитів - для логування в розробці:
// AppServiceProvider::boot()
if (app()->isLocal()) {
DB::listen(function (QueryExecuted $query): void {
Log::debug($query->toRawSql(), ['ms' => $query->time]);
});
}
Сповіщення про повільну роботу з базою за весь запит:
DB::whenQueryingForLongerThan(500, function (Connection $connection, QueryExecuted $event): void {
Log::warning('Багато часу в базі', ['connection' => $connection->getName()]);
});
Як знайти проблеми системно:
- N+1:
Model::preventLazyLoading(! app()->isProduction())- виняток при лінивому завантаженні зв'язку в циклі; - Laravel Debugbar чи Telescope - список запитів сторінки з дублікатами й часом;
- сторінка помилки Laravel також показує виконані запити;
- на продакшені - журнал повільних запитів бази (
pg_stat_statements, slow query log), а не логування кожного запиту.
Пастка: enableQueryLog у довгому процесі (воркер, команда з мільйоном записів) накопичує всі запити в пам'яті - вмикайте його лише на час налагодження.