Il y a des situations qui nécessitent d'avoir une très grosse requête joignant plusieurs tables avec des instructions de sous-sélection pour produire les résultats souhaités.
Ma question est la suivante: devrions-nous envisager d'utiliser plusieurs requêtes plus petites et intégrer les opérations logiques dans la couche application en interrogeant la base de données en plusieurs appels ou est-il préférable de les avoir toutes en une seule fois?
Par exemple, considérez la requête suivante:
SELECT *
FROM `users`
WHERE `user_id` IN (SELECT f2.`friend_user_id`
FROM `friends` AS f1
INNER JOIN `friends` AS f2
ON f1.`friend_user_id` = f2.`user_id`
WHERE f2.`is_page` = 0
AND f1.`user_id` = "%1$d"
AND f2.`friend_user_id` != "%1$d"
AND f2.`friend_user_id` NOT IN (SELECT `friend_user_id`
FROM `friends`
WHERE `user_id` = "%1$d"))
AND `user_id` NOT IN (SELECT `user_id`
FROM `friend_requests`
WHERE `friend_user_id` = "%1$d")
AND `user_image` IS NOT NULL
ORDER BY RAND()
LIMIT %2$d
Quelle est la meilleure façon de procéder?
la source
En tant que personne qui doit prendre en charge / nettoyer ces requêtes volumineuses et compliquées, je dirais qu'il est préférable de les diviser en plusieurs petits morceaux faciles à comprendre. Ce n'est pas nécessairement mieux du point de vue des performances, mais vous donnez au moins à SQL une meilleure chance de proposer un bon plan de requête.
Rendez la vie plus facile aux gens qui vous suivent et ils vous diront de bonnes choses. Rendez-les durs et ils vous maudiront.
la source
Mes 2 cents sur les performances et l'évolutivité des requêtes de 2 mots clés:
Performances des requêtes : le parallélisme SQL Server fait déjà un très bon travail en décomposant les requêtes en recherches multi-threads, donc je ne sais pas dans quelle mesure vous améliorerez les performances des requêtes en le faisant pour SQL Server. Cependant, vous devrez regarder le plan d'exécution pour voir le degré de parallélisme que vous obtenez lorsque vous l'exécutez et comparer les résultats dans les deux sens. Si vous finissez par avoir à utiliser un indice de requête pour obtenir des performances identiques ou meilleures, alors l'OMI ne vaut pas la peine car l'indice de requête pourrait ne pas être optimal plus tard.
Évolutivité: la lecture des requêtes peut être plus facile, comme l'indique le code de données, et la diviser en requêtes distinctes est logique si vous pouvez également utiliser vos nouvelles requêtes dans d'autres domaines, mais si vous ne les utilisez pas également pour d'autres appels, alors ce sera encore plus de processus stockés à gérer pour 1 tâche, et IMO ne contribuerait pas à l'évolutivité.
la source
LIMIT
Parfois, il n'y a pas d'autre choix que de diviser la requête grande / complexe en petites requêtes. La meilleure façon de déterminer cela serait d'utiliser l'
EXPLAIN
instruction avec l'SELECT
instruction. Le nombre de traces / analyses que votre base de données va effectuer pour récupérer vos données est le produit des valeurs de "lignes" renvoyées par votreEXPLAIN
requête. Dans notre cas, nous avons eu une requête joignant 10 tables. Pour un record particulier, la trace s'élevait à 409M qui bloguait notre base de données et poussait notre utilisation CPU de notre serveur DB plus de 300%. Nous avons pu récupérer les mêmes informations en fractionnant les requêtes beaucoup plus rapidement.Donc, en bref, dans certains cas, le fractionnement d'une requête complexe / volumineuse est logique, mais dans d'autres, cela peut entraîner de nombreux problèmes de performances ou de maintenance et cela doit être traité au cas par cas.
la source