Autour de Laravel

Optimisation requête avec Eloquent

Avatar de Seeryos
Seeryos

Bonjour à toutes et à tous,

Petite question niveau optimisation.

J'ai écris cette requête

$posts_ids = \DB::table('post_tag')->select('post_id')->where('tag_id', $tag->id)->groupBy('post_id')->skip(0)->take(999)->pluck('post_id')->toArray();

$posts = Post::select('id', 'slug', 'img', 'description', 'title')->whereIntegerInRaw('id', $posts_ids)->orderBy('sponso', 'desc')->orderBy('order', 'asc')->with('badges', 'tags')->simplePaginate($this->postPerPage);

Tout fonctionne nickel sur mon serveur mutualisé et mon serveur local. Par contre, si mon serveur dédié sous Ubuntu, le champ "data" du paginate me retourne toujours un tableau vide.

La raison ? Quand posts_id comprend plus de 999 posts, un bug de mariadb fait qu'un whereIn avec un tableau de plus 999 entrée renverra toujours un tableau vide. https://jira.mariadb.org/browse/MDEV-27937

J'attends que le correctif soit dispo sur ubuntu mais j'aimerais votre avis quant aux performances de cette requête ? Avez-vous déjà eu le souci ? J'ai valorisé un whereIn plutôt que des jointures car cela me semblait plus rapide en exécution (un post peut disposer de plusieurs tags, plusieurs catégories, etc).

Pour patcher ma pagination en attendant j'ai donc écris

$posts_ids = \DB::table('post_tag')->select('post_id')->where('tag_id', $tag->id)->groupBy('post_id')->skip(0)->take(999)->pluck('post_id')->toArray();

Mais du coup c'est un peu bête de pas pouvoir afficher tous mes posts en rapport avec un certain tag dans mon backoffice...

Merci pour votre aide !

Posté il y a 1 an
Avatar de khalyomede
khalyomede

Bonsoir,

Que penses-tu d'écrire ta requête d'une seule traite plutôt que de passer par un appel à DB supplémentaire ? Ca nécessitera que ta relation "tags" dans le modèle "Post" soit bien formée.

$posts = Post::query()
    ->select([
        "id",
        "slug",
        "img",
        "description",
        "title",
    ])
    ->whereHas("tags", function ($tags) use ($tag) {
        return $tags->wherePivot("tag_id", $tag->id);
    })
    ->orderByDesc("sponso")
    ->with([
        "badges",
        "tags"
    ])
    ->simplePaginate($this->postPerPages);

Garde un oeil sur ton nombre de requête avant/après mettre ce code, si ça peut t'économiser une requête c'est bien pour ne pas surcharger ton serveur MariaDB.

Posté il y a 1 an
Avatar de Seeryos
Seeryos

Je vais jeter un oeil là dessus ! Merci ! Par contre, es-tu certains que le whereHas ne créé par une requête assez lourde ? Je me méfie toujours des requêtes autogénérées.

Posté il y a 1 an

Vous ne pouvez pas répondre à ce sujet.