web-dev-qa-db-fra.com

Qu'est-ce qui est plus rapide, une grande requête ou plusieurs petites requêtes?

J'ai travaillé pour différentes entreprises, et j'ai remarqué que certaines d'entre elles préfèrent avoir des vues qui rejoindront une table avec tous ses "proches". Mais ensuite sur l'application quelques fois, nous n'avons besoin que d'une seule colonne.

Serait-il donc plus rapide de faire simplement des sélections simples, puis de les "joindre" sur le code système?

Le système peut être php, Java, asp, n'importe quel langage qui se connecte à la base de données.

La question est donc de savoir ce qui est plus rapide pour passer d'un côté serveur (php, Java, asp, Ruby, python ...) à la base de données, exécuter une requête qui obtient tout ce dont nous avons besoin ou passer du côté serveur à la base de données et exécuter un requête qui n'obtient que les colonnes d'une table à la fois?

76
sudo.ie

Ce qui répondrait à votre question est le sujet REJOINDRE LA DÉCOMPOSITION.

Selon page 209 du livre

High Performance MySQL

Vous pouvez décomposer une jointure en exécutant plusieurs requêtes à table unique au lieu d'une jointure multitable, puis en effectuant la jointure dans l'application. Par exemple, au lieu de cette seule requête:

SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
WHERE tag.tag = 'mysql';

Vous pouvez exécuter ces requêtes:

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

Pourquoi diable feriez-vous cela? Cela semble inutile à première vue, car vous avez augmenté le nombre de requêtes sans rien obtenir en retour. Cependant, une telle restructuration peut en fait offrir des avantages de performance importants:

  • La mise en cache peut être plus efficace. De nombreuses applications mettent en cache des "objets" qui sont directement mappés aux tables. Dans cet exemple, si l'objet avec la balise mysql est déjà mis en cache, l'application ignorera la première requête. Si vous trouvez des publications avec un ID de 123, 567 ou 908 dans le cache, vous pouvez les supprimer de la liste IN(). Le cache de requêtes peut également bénéficier de cette stratégie. Si une seule des tables change fréquemment, la décomposition d'une jointure peut réduire le nombre d'invalidations du cache.
  • L'exécution individuelle des requêtes peut parfois réduire les conflits de verrouillage
  • Les jointures dans l'application facilitent la mise à l'échelle de la base de données en plaçant des tables sur différents serveurs.
  • Les requêtes elles-mêmes peuvent être plus efficaces. Dans cet exemple, l'utilisation d'une liste IN() au lieu d'une jointure permet à MySQL de trier les ID de ligne et de récupérer les lignes de manière plus optimale qu'il ne serait possible avec une jointure.
  • Vous pouvez réduire les accès aux lignes redondantes. Faire une jointure dans l'application signifie récupérer chaque ligne une seule fois., Tandis qu'une jointure dans la requête est essentiellement une dénormalisation qui peut accéder à plusieurs reprises aux mêmes données. Pour la même raison, une telle restructuration pourrait également réduire le trafic réseau total et l'utilisation de la mémoire.
  • Dans une certaine mesure, vous pouvez voir cette technique comme implémentant manuellement une jointure de hachage au lieu de l'algorithme de boucles imbriquées que MySQL utilise pour exécuter une jointure. Une jointure par hachage peut être plus efficace.

Par conséquent, faire des jointures dans l'application peut être plus efficace lorsque vous mettez en cache et réutilisez un grand nombre de données provenant de requêtes antérieures, vous distribuez des données sur plusieurs serveurs, vous remplacez les jointures par des listes IN(), ou une jointure fait référence à la même table plusieurs fois.

OBSERVATION

J'aime le premier point parce qu'InnoDB est un peu lourd lorsqu'il vérifie le cache des requêtes.

En ce qui concerne le dernier point, j'ai écrit un article le 11 mars 2013 ( y a-t-il une différence d'exécution entre une condition JOIN et une condition WHERE? ) qui décrit l'algorithme de boucle imbriquée. Après l'avoir lu, vous verrez à quel point la décomposition des jointures peut être bonne.

Comme pour tous les autres points du livre , les développeurs recherchent vraiment la performance comme résultat. Certains s'appuient sur des moyens externes (en dehors de l'application) pour des améliorations de performances telles que l'utilisation d'un disque rapide, l'obtention de plus de CPU/cœurs, le réglage du moteur de stockage et le réglage du fichier de configuration. D'autres vont boucler et écrire un meilleur code. Certains peuvent avoir recours au codage de l'intelligence d'affaires dans les procédures stockées mais n'appliquent toujours pas la décomposition des jointures (voir Quels sont les arguments contre ou pour mettre la logique d'application dans la couche de base de données? avec les autres messages). Tout dépend de la culture et de la tolérance de chaque boutique de développeur.

Certains peuvent être satisfaits des performances et ne plus toucher au code. D'autres ne réalisent tout simplement pas qu'il existe de grands avantages que l'on peut retirer s'ils essaient de se joindre à la composition.

Pour les développeurs qui le souhaitent ...

ESSAIE !!!

73
RolandoMySQLDBA

Dans Postgres (et probablement n'importe quel SGBDR dans une mesure similaire, MySQL dans une moindre mesure), moins de requêtes sont presque toujours beaucoup plus rapide.

La surcharge de l'analyse et de la planification de plusieurs requêtes est déjà plus que tout gain possible dans la plupart des cas.

Sans parler du travail supplémentaire à faire chez le client, en combinant les résultats, ce qui est généralement beaucoup plus lent à cela. Un SGBDR est spécialisé dans ce type de tâche et les opérations sont basées sur des types de données originaux. Pas de transtypage vers text et retour pour des résultats intermédiaires ou transformation en types natifs du client, ce qui peut même conduire à des résultats moins corrects (ou incorrects!). Pensez aux nombres à virgule flottante ...

Vous transférez également plus de données entre le serveur de base de données et le client. Cela peut être négligeable pour une main pleine de valeurs, ou faire une énorme différence.

Si plusieurs requêtes signifient plusieurs allers-retours vers le serveur de base de données, vous collectez également plusieurs fois la latence du réseau et la surcharge de transaction, voire la surcharge de connexion. Grande, grosse perte.

Selon votre configuration, la latence du réseau à elle seule peut prendre plus de temps que tous les autres par ordre de grandeur.

Question connexe sur SO:

Il peut y avoir un tournant pour très grand, des requêtes de longue durée car les transactions collectent des verrous sur les lignes de base de données en cours de route. Les requêtes très volumineuses peuvent contenir de nombreux verrous pendant une période prolongée, ce qui peut provoquer des frictions avec requêtes simultanées.

29
Erwin Brandstetter