Je souhaite appliquer une condition where
à la relation. Voici ce que je fais:Mauvaise performance whereHas dans Laravel
Replay::whereHas('players', function ($query) {
$query->where('battletag_name', 'test');
})->limit(100);
Il génère la requête suivante:
select * from `replays`
where exists (
select * from `players`
where `replays`.`id` = `players`.`replay_id`
and `battletag_name` = 'test')
order by `id` asc
limit 100;
qui exécute en 70 secondes. Si je réécris manuellement la requête comme ceci:
select * from `replays`
where id in (
select replay_id from `players`
where `battletag_name` = 'test')
order by `id` asc
limit 100;
Il s'exécute en 0.4 secondes. Pourquoi where exists
est le comportement par défaut si c'est si lent? Existe-t-il un moyen de générer la bonne requête where in
avec le constructeur de requête ou ai-je besoin d'injecter du SQL brut? Peut-être que je fais quelque chose de mal tout à fait?
replays
table a 4M lignes, players
a 40M lignes, toutes les colonnes pertinentes sont indexées, le jeu de données ne rentre pas dans la mémoire du serveur MySQL.
Mise à jour: a constaté que la requête correcte peut être générée comme:
Replay::whereIn('id', function ($query) {
$query->select('replay_id')->from('players')->where('battletag_name', 'test');
})->limit(100);
ont encore une question pourquoi exists
exécute si mal et pourquoi il est le comportement par défaut
Je suggère Do not SELECT * .. Essayez de SELECT attribut spécifique au lieu de tous. – parkway
Je dois tous les sélectionner pour mon cas. Et même en sélectionnant uniquement la colonne 'id' améliore les performances des requêtes de moins de 1%, il est donc négligeable. – Poma