web-dev-qa-db-fra.com

Les jointures sont pour les paresseux?

J'ai récemment eu une discussion avec un autre développeur qui m'a affirmé que les JOIN (SQL) sont inutiles. C'est techniquement vrai, mais il a ajouté que l'utilisation de jointures est moins efficace que de faire plusieurs requêtes et tables de liens dans le code (C # ou Java).

Pour lui, les jointures sont pour les gens paresseux qui ne se soucient pas de la performance. Est-ce vrai? Faut-il éviter d'utiliser des jointures?

167
Bastien Vandamme

Non, nous devons éviter les développeurs qui ont des opinions incroyablement fausses.

Dans de nombreux cas, une jointure de base de données est plusieurs ordres de grandeur plus rapide que tout ce qui se fait via le client, car elle évite les allers-retours DB et la base de données peut utiliser des index pour effectuer la jointure.

Du haut de ma tête, je ne peux même pas imaginer un seul scénario où une jointure correctement utilisée serait plus lente que l'opération côté client équivalente.

Edit: Il existe de rares cas où le code client personnalisé peut faire les choses plus efficacement qu'une simple jointure de base de données (voir commentaire par meriton). Mais c'est vraiment l'exception.

187

Il me semble que votre collègue ferait bien avec une base de données de documents sans SQL ou un magasin de valeurs-clés. Qui sont eux-mêmes de très bons outils et adaptés à de nombreux problèmes.

Cependant, une base de données relationnelle est fortement optimisée pour travailler avec des ensembles. Il existe de nombreuses façons d'interroger les données basées sur des jointures qui sont largement plus efficaces que de nombreux allers-retours. C'est de là que vient la polyvalence d'un rdbms. Vous pouvez également obtenir le même résultat dans un magasin nosql, mais vous finissez souvent par créer une structure distincte adaptée à chaque nature différente de la requête.

En bref: je ne suis pas d'accord. Dans un SGBDR, les jointures sont fondamentales . Si vous ne les utilisez pas, vous ne les utilisez pas en tant que SGBDR.

83
Marc Gravell

Eh bien, il a tort dans le cas général.

Les bases de données sont capables d'optimiser en utilisant une variété de méthodes, aidées par des conseils d'optimiseur, des index de table, des relations de clé étrangère et éventuellement d'autres informations spécifiques au fournisseur de base de données.

46
sehe

Si "paresseux" est défini comme des personnes qui veulent écrire moins de code, alors je suis d'accord. Si "paresseux" est défini comme des personnes qui veulent que les outils fassent ce qu’ils sont bons à faire, je suis d’accord. Donc, s'il est simplement d'accord avec Larry Wall (concernant les attributs de bons programmeurs), je suis d'accord avec lui.

19
MJB

Ummm, jointures est la façon dont les bases de données relationnelles relient les tables entre elles. Je ne sais pas où il veut en venir.

Comment faire plusieurs appels à la base de données peut être plus efficace qu'un appel? De plus, les moteurs SQL sont optimisés pour faire ce genre de chose.

Peut-être que votre collègue est trop paresseux pour apprendre SQL.

16
Giovanni Galbo

Oui tu devrais.

Et vous devez utiliser C++ au lieu de C # en raison des performances. C # est pour les paresseux.

Non non Non. Vous devez utiliser C au lieu de C++ en raison des performances. C++ est destiné aux paresseux.

Non non Non. Vous devez utiliser Assembly au lieu de C en raison des performances. C est pour les paresseux.

Oui, je plaisante. vous pouvez créer des programmes plus rapides sans jointures et vous pouvez créer des programmes utilisant moins de mémoire sans jointures. MAIS dans de nombreux cas, votre temps de développement est plus important que le temps CPU et la mémoire. Abandonnez un peu de performance et profitez de votre vie. Ne perdez pas votre temps pour peu de petites performances. Et dites-lui: "Pourquoi ne fais-tu pas une route droite de chez toi à ton bureau?"

12
RedPain

"C'est techniquement vrai" - de la même manière, une base de données SQL est inutile: à quoi bon en utiliser une quand on peut obtenir le même résultat en utilisant un tas de fichiers CSV et en les corrélant dans le code? Heck, toute abstraction est pour les paresseux, revenons à la programmation en code machine directement sur le matériel! ;)

En outre, son assertion est fausse dans tous les cas sauf les plus compliqués: les SGBDR sont fortement optimisés pour rendre les JOIN rapides . Relational systèmes de gestion de base de données, non?

11
Piskvor

La dernière entreprise pour laquelle j'ai travaillé n'a pas non plus utilisé de jointures SQL. Au lieu de cela, ils ont déplacé ce travail vers la couche d'application qui est conçue pour évoluer horizontalement. La justification de cette conception est d'éviter de travailler sur la couche de base de données. C'est généralement la base de données qui devient un goulot d'étranglement. Il est plus facile de répliquer la couche d'application que la base de données. Il pourrait y avoir d'autres raisons. Mais c'est celle dont je me souviens maintenant.

Oui, je suis d'accord que les jointures effectuées au niveau de la couche application sont inefficaces par rapport aux jointures effectuées par la base de données. Plus de communication réseau également.

Veuillez noter que je ne prends pas fermement position pour éviter les jointures SQL.

7
Srikanth

Prenons un exemple: une table avec des enregistrements de facture et une table associée avec des enregistrements d'élément de ligne de facture. Considérez le pseudo-code client:

for each (invoice in invoices)
    let invoiceLines = FindLinesFor(invoice)
...

Si vous avez 100 000 factures de 10 lignes chacune, ce code recherchera 10 lignes de facture dans un tableau de 1 million, et il le fera 100 000 fois. À mesure que la taille de la table augmente, le nombre d'opérations de sélection augmente, et le coût de chaque opération de sélection augmente.

Étant donné que les ordinateurs sont rapides, vous ne remarquerez peut-être pas de différence de performances entre les deux approches si vous avez plusieurs milliers d'enregistrements ou moins. Parce que l'augmentation des coûts est plus que linéaire, à mesure que le nombre d'enregistrements augmente (en millions, par exemple), vous commencerez à remarquer une différence, et la différence deviendra moins tolérable à mesure que la taille de l'ensemble de données augmentera.

La jointure, cependant. utilisera les index de la table et fusionnera les deux ensembles de données. Cela signifie que vous analysez efficacement la deuxième table une fois plutôt que d'y accéder de manière aléatoire N fois. Si une clé étrangère est définie, la base de données a déjà les liens entre les enregistrements associés stockés en interne.

Imaginez faire cela vous-même. Vous avez une liste alphabétique des étudiants et un cahier avec tous les rapports de notes des étudiants (une page par classe). Le cahier est trié par ordre de nom des élèves, dans le même ordre que la liste. Comment préférez-vous procéder?

  1. Lisez un nom de la liste.
  2. Ouvrez le cahier.
  3. Trouvez le nom de l'élève.
  4. Lisez les notes de l'élève en tournant les pages jusqu'à ce que vous atteigniez l'étudiant suivant ou la dernière page.
  5. Fermez le cahier.
  6. Répéter.

Ou:

  1. Ouvrez le bloc-notes à la première page.
  2. Lisez un nom de la liste.
  3. Lisez les notes de ce nom dans le cahier.
  4. Répétez les étapes 2 et 3 jusqu'à la fin
  5. Fermez le cahier.
5
phoog

Sans jointures, comment allez-vous relier les articles de commande aux commandes? C'est tout l'intérêt d'un système de gestion de bases de données relationnelles. Sans jointures, il n'y a pas de données relationnelles et vous pourriez aussi bien utiliser des fichiers texte pour traiter les données.

On dirait qu'il ne comprend pas le concept, alors il essaie de faire croire qu'ils sont inutiles. C'est le même type de personne qui pense qu'Excel est une application de base de données. Giflez-le bêtement et dites-lui d'en savoir plus sur les bases de données. Faire plusieurs connexions et extraire des données et fusionner les données via C # est la mauvaise façon de faire les choses.

5
JonH

Cela ressemble à un cas classique de "je peux mieux l'écrire." En d'autres termes, il voit quelque chose qu'il considère comme une sorte de douleur dans le cou (en écrivant un tas de jointures en SQL) et en disant: "Je suis sûr que je peux mieux l'écrire et obtenir de meilleures performances." Vous devez lui demander s'il est a) plus intelligent et b) plus éduqué que la personne type qui est profondément ancrée dans le code d'optimisation Oracle ou SQL Server. Il y a de fortes chances qu'il ne le soit pas.

5
jcollum

Je ne comprends pas la logique de la déclaration "les jointures en SQL sont inutiles". Est-il utile de filtrer et de limiter les données avant de travailler dessus? Comme vous êtes d'autres répondants, c'est ce que font les moteurs de base de données, ce devrait être leur domaine.

Peut-être qu'un programmeur paresseux s'en tiendrait aux technologies qu'il connaissait et éviterait d'autres possibilités pour des raisons non techniques.

Je vous laisse décider.

5
Jodrell

Je soupçonne qu'il a une vue limitée sur les bases de données à utiliser. Une approche pour maximiser les performances consiste à lire l'intégralité de la base de données en mémoire. Dans cette situation, vous pouvez obtenir de meilleures performances et vous pouvez effectuer des jointures si la mémoire est efficace. Cependant, cela n'utilise pas vraiment une base de données, comme une base de données à mon humble avis.

3
Peter Lawrey

Il a très certainement tort. Bien qu'il existe des avantages certains à la manipulation des données dans des langages comme C # ou Java, les jointures sont plus rapides dans la base de données en raison de la nature de SQL lui-même.

SQL continue de détailler les statistiques concernant les données et, si vous avez créé correctement vos index, peut très rapidement trouver un enregistrement sur quelques millions. Outre le fait que pourquoi voudriez-vous faire glisser toutes vos données dans C # pour faire une jointure alors que vous pouvez simplement le faire directement au niveau de la base de données?

Les avantages de l'utilisation de C # entrent en jeu lorsque vous devez faire quelque chose de manière itérative. Si vous devez effectuer une fonction pour chaque ligne, il est probablement plus rapide de le faire en C #, sinon, la jonction des données est optimisée dans la base de données.

3
Mike M.

Je dirai que j'ai rencontré un cas où il était plus rapide de décomposer la requête et de faire les jointures dans le code. Cela étant dit, ce n'est qu'avec une version particulière de MySQL que j'ai dû le faire. Tout le reste, la base de données sera probablement plus rapide (notez que vous devrez peut-être optimiser les requêtes, mais ce sera toujours plus rapide).

3
JaCraig

Non, non seulement les jointures sont mieux optimisées dans le code de la base de données que C #/Java ad-hoc; mais généralement plusieurs techniques de filtrage peuvent être appliquées, ce qui donne des performances encore meilleures.

2
Jonas Byström

J'ai entendu cet argument assez souvent au cours de ma carrière de développeur de logiciels. Presque chaque fois que cela a été déclaré, le type qui faisait la réclamation n'avait pas beaucoup de connaissances sur les systèmes de bases de données relationnelles, la façon dont ils fonctionnent et la façon dont ces systèmes devraient être utilisés.

Oui, lorsqu'ils sont utilisés incorrectement, les jointures semblent inutiles, voire dangereuses. Mais lorsqu'il est utilisé correctement, il y a beaucoup de potentiel pour l'implémentation de la base de données pour effectuer des optimisations et pour "aider" le développeur à récupérer le résultat correct plus efficacement.

N'oubliez pas qu'en utilisant un JOIN, vous informez la base de données de la façon dont vous vous attendez à ce que les éléments de données soient liés les uns aux autres et donnez donc à la base de données plus d'informations sur quoi que vous essayez à faire et donc à mieux répondre à vos besoins.

La réponse est donc définitivement: non, JOINS ne sont pas du tout inutiles!

2
perdian

Sauf si j'ai sérieusement mal compris, la logique de la question est très imparfaite

S'il y a 20 lignes en B pour chaque A, 1000 lignes en A impliquent 20k lignes en B. Il ne peut pas y avoir seulement 100 lignes en B à moins qu'il y ait plusieurs-table "AB" avec 20k lignes avec le contenant le mappage .

Donc, pour obtenir toutes les informations sur lesquelles 20 des 100 lignes B correspondent à chaque ligne A, vous table AB aussi. Ce serait donc soit:

  • 3 jeux de résultats de 100, 1000 et 20k lignes et un client JOIN
  • un seul jeu de résultats JOIN-A-AB-B avec 20k lignes

Ainsi, "JOIN" dans le client ajoute une valeur lorsque vous examinez les données. Non pas que ce ne soit pas une mauvaise idée. Si je récupérais un objet de la base de données, il serait peut-être plus logique de le décomposer en ensembles de résultats distincts. Pour un appel de type rapport, je l'aplatirais presque toujours.

En tout cas, je dirais qu'il n'y a presque aucune utilité pour une jointure croisée de cette ampleur. C'est un mauvais exemple.

Vous devez vous JOINDRE quelque part, et c'est à cela que les SGBDR sont bons. Je ne voudrais pas travailler avec un singe de code client qui pense pouvoir faire mieux.

Après coup:

Pour rejoindre le client, il faut des objets persistants tels que DataTables (en .net). Si vous avez un jeu de résultats aplati, il peut être consommé via quelque chose de plus léger comme un DataReader. Volume élevé = beaucoup de ressources client utilisées pour éviter une base de données JOIN.

0
gbn

Ceci n'est "techniquement vrai" que dans un cas qui n'est pas souvent utilisé dans les applications (lorsque toutes les lignes de toutes les tables des jointures sont renvoyées par la requête). Dans la plupart des requêtes, seule une fraction des lignes de chaque table est renvoyée. Le moteur de base de données utilise souvent des index pour éliminer les lignes indésirables, parfois même sans lire la ligne réelle car il peut utiliser les valeurs stockées dans les index. Le moteur de base de données est lui-même écrit en C, C++, etc. et est au moins aussi efficace que le code écrit par un développeur.

0
fredt