Les jointures sont pour les paresseux?

169

J'ai récemment eu une discussion avec un autre développeur qui me disait 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 lier des tables dans le code (C # ou Java).

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

Bastien Vandamme
la source
114
Les bases de données sont optimisées pour effectuer des jointures, elles sont extrêmement rapides en particulier pour les grands ensembles de données. Vous ne voulez pas que votre application charge des dizaines de milliers de lignes et les fusionne manuellement.
halfdan
91
Les langages de programmation sont pour les paresseux; ils sont moins efficaces que le codage manuel des instructions CPU. :)
Michael McGowan
76
Quel est le nom du développeur? Je veux m'assurer de ne jamais l'embaucher.
Joe
39
@Michael meh, les vrais programmeurs utilisent des papillons ...
Marc Gravell
14
Re votre "c'est vrai" - non, ce n'est pas le cas. Les bases de données fonctionnent via la théorie des ensembles; les jointures sur les décors fonctionnent très bien et utilement ...
Marc Gravell

Réponses:

188

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

Dans de nombreux cas, une jointure de base de données est de plusieurs ordres de grandeur plus rapide que tout ce qui est fait via le client, car elle évite les allers-retours de base de données, 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 équivalente côté client.

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

Michael Borgwardt
la source
1
Qu'en est-il des jointures à trois voies? N'y a-t-il pas des cas où vous feriez mieux de les faire "en code"?
julien_c
56
La connexion au serveur d'applications peut être plus efficace si la participation à la base de données entraîne une redondance sévère dans l'ensemble de résultats envoyé sur le réseau. Considérez les tables A et B, où chaque ligne de A est associée à 20 lignes de B, B n'a que 100 lignes, et nous voulons récupérer les 1000 premières lignes de A avec les lignes associées de B. Rejoindre la base de données entraînera 20 * 1000 tuples envoyés sur le réseau. Si la jointure est effectuée dans le serveur d'applications (en récupérant d'abord toute la table B en mémoire), à ​​peine 100 + 1000 lignes sont envoyées sur le réseau.
meriton
7
Cependant, vous avez certainement raison en ce sens que les jointures sur la base de données sont beaucoup plus rapides dans la plupart des cas, et donc pas seulement une question de commodité, mais de nécessité.
meriton
13
J'ai eu la chance de parler avec certains des développeurs qui travaillent sur SQL Server chez Microsoft. Cela vous donnera le vertige d'entendre les optimisations qu'ils font sur les requêtes. Quiconque pense être plus intelligent que cela doit être frappé.
riwalk
2
@meriton je suis un peu surpris; Je m'attendrais à ce que la bibliothèque cliente optimise les jointures croisées.
Phil Lello
83

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. Ce sont eux-mêmes de très bons outils et une bonne solution pour de nombreux problèmes.

Cependant, une base de données relationnelle est fortement optimisée pour travailler avec des ensembles. Il y a beaucoup de façons d'interroger les données basées sur les jointures qui sont largement plus efficaces que beaucoup de voyages aller - retour. C'est de là que vient la polyvalence d'un rdbms. Vous pouvez également obtenir la même chose 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 comme SGBDR.

Marc Gravell
la source
46

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

Les bases de données sont capables d'optimiser à l'aide de diverses méthodes, aidées par des conseils d'optimisation, des index de table, des relations de clé étrangère et éventuellement d'autres informations spécifiques au fournisseur de bases de données.

sehe
la source
1
Je dois admettre que lorsque j'ai commencé à travailler avec des bases de données, j'avais la même conviction que je pouvais battre les performances des jointures. Mais il n'a pas fallu longtemps pour réaliser à quel point les jointures incroyablement rapides sont effectuées par la base de données. En fait, je dirais que dans cette situation, il vaut mieux en discuter avec l'employé de manière ouverte plutôt que de le rejeter comme un idiot.
LegendLength
1
@LegendLength Je dirais que c'est même vrai s'ils ne sont pas si intelligents. Inutile de présumer de l'intelligence car ils font les mêmes erreurs que nous nous souvenons d'avoir faites (en fait, pour moi, cela pourrait signifier qu'ils ne sont pas si intelligents ...) C'est plus simple: cela aide rarement à être dédaigneux. Il est normal de se tromper, de temps en temps!
sehe
24

Non, tu ne devrais pas.

Les bases de données sont spécifiquement conçues pour manipuler des ensembles de données (évidemment…). Par conséquent, ils sont incroyablement efficaces pour ce faire. En faisant ce qui est essentiellement une jointure manuelle dans son propre code, il tente de reprendre le rôle de quelque chose spécialement conçu pour le travail. Les chances que son code soit toujours aussi efficace que celui de la base de données sont très faibles.

En passant, sans jointures, quel est l'intérêt d'utiliser une base de données? il peut tout aussi bien utiliser des fichiers texte.

Richzilla
la source
2
Même sans jointure? Mappage automatique en mémoire, mise en cache automatique des requêtes, beaucoup d'autres choses automagiques qui ne se produisent pas du tout avec la plupart des systèmes de fichiers. Oh, ai-je mentionné des transactions finement contrôlables?
Piskvor a quitté le bâtiment le
19

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 pour quoi ils sont bons, je suis d'accord. Donc, s'il est simplement d'accord avec Larry Wall (concernant les attributs des bons programmeurs), alors je suis d'accord avec lui.

MJB
la source
J'ai ajouté la précision du paresseux: pour les paresseux qui ne se soucient pas des performances et préfèrent écrire moins de code. Je pense que les jointures sont pour les paresseux, mais dans ce cas, les jointures sont également meilleures que plusieurs demandes.
Bastien Vandamme
3
@Dran Dane: Les jointures sont pour les paresseux, oui. Le fait qu'ils fonctionneront probablement bien est orthogonal.
Piskvor a quitté le bâtiment le
16

Ummm, les jointures sont la façon dont les bases de données relationnelles relient les tables les unes aux autres. Je ne sais pas trop où il veut en venir.

Comment faire plusieurs appels à la base de données peut-il être plus efficace qu'un seul 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.

Giovanni Galbo
la source
12

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 pour les paresseux.

Non non Non. Vous devez utiliser l'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 jointure et vous pouvez créer des programmes utilisant moins de mémoire sans jointure. 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 de petites performances. Et dites-lui "Pourquoi ne pas faire une autoroute directe de chez vous à votre bureau?"

RedDouleur
la source
1
J'ai regardé toutes vos réponses jusqu'à présent et elles sont très drôles. S'il vous plaît, continuez à venir. Soit cela, soit, où puis-je m'abonner à votre blog?
Gerry
11

"C'est techniquement vrai" - de même, une base de données SQL est inutile: quel est l'intérêt d'en utiliser une quand vous pouvez 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! ;)

De plus, son affirmation est fausse dans tous les cas sauf les plus compliqués: les SGBDR sont fortement optimisés pour rendre les JOINs rapides . Systèmes de gestion de bases de données relationnelles , non?

Piskvor a quitté le bâtiment
la source
2
+1 L'expression "... techniquement vrai" aurait mieux fonctionné si l'OP avait utilisé le mot unnecessaryplutôt uselessdans la phrase précédente. Dire que les jointures sont inutiles est manifestement faux et qu'aucune technique n'a besoin d'être prise en compte. Dans tous les cas, l'incompréhension du PO et du collègue sur l'intérêt des SGBDR n'est pas rare: stackoverflow.com/q/5575682/47550
Paul Sasik
7

La dernière entreprise pour laquelle j'ai travaillé n'utilisait pas non plus de jointures SQL. Au lieu de cela, ils ont déplacé ce travail vers la couche d'application qui est conçue pour être mise à l'échelle horizontalement. La justification de cette conception est d'éviter le travail au niveau de la couche de base de données. C'est généralement la base de données qui devient le 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 celui dont je me souviens maintenant.

Oui, je reconnais 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.

Srikanth
la source
Eh bien, cela ressemble à un argument rationnel contre les JOIN dans votre cas spécifique. Je me souviens que FB Engineering a publié quelque chose de similaire sur son blog - la mise à l'échelle était également leur priorité principale. Hélas, seul un petit% des programmeurs aura besoin de le faire, mais beaucoup pensent qu'ils le font "parce que OMG Facebook fait aussi cela";)
Piskvor a quitté le bâtiment le
d'accord, dans une solution d'entreprise où vous avez suffisamment de trafic pour surcharger le serveur de base de données, cela peut valoir la peine d'être pris en compte, mais il est plus probable qu'il s'agisse de la procédure stockée de rapport ou de la sauvegarde planifiée qui cloue les performances. Les bases de données sont bonnes pour les jointures, surtout s'il y a des indécies pour aider
Jodrell
@Jodrell: Oui, ils sont bons pour les jointures; encore une fois, il existe des cas d'angle où vous devez abandonner l'élégance des jointures pour obtenir plus de puissance. J'ai rencontré une telle situation; nous avons essayé toutes les solutions possibles, et en fait, une solution sans jointure était la plus rapide dans cette situation très spécifique . Et non, il n'y avait rien d'autre en cours d'exécution sur ce serveur particulier; les procédures stockées ne peuvent pas vous ralentir si vous n'en avez pas;)
Piskvor a quitté le bâtiment le
5

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 base de données relationnelle. Sans jointures, il n'y a pas de données relationnelles et vous pouvez également 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 idiot et dites-lui d'en savoir plus sur les bases de données. Établir plusieurs connexions, extraire des données et fusionner les données via C # n'est pas la bonne façon de faire les choses.

JonH
la source
5

Je ne comprends pas la logique de l'instruction "les jointures en SQL sont inutiles". Est-il utile de filtrer et de limiter les données avant de travailler dessus? Comme vous l’avez dit d’autres répondants, c’est ce que font les moteurs de base de données.

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

Je vous laisse le soin de décider.

Jodrell
la source
5

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. Étant donné que l'augmentation des coûts est plus que linéaire, à mesure que le nombre d'enregistrements augmente (par exemple en millions), vous commencerez à remarquer une différence, et la différence deviendra moins tolérable à mesure que la taille de l'ensemble de données augmente.

La jointure, cependant. utilisera les index de la table et fusionnera les deux ensembles de données. Cela signifie que vous scannez effectivement la deuxième table une fois plutôt que d'y accéder aléatoirement 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 élèves et un cahier avec tous les rapports de notes des élèves (une page par classe). Le cahier est trié en fonction des noms des élèves, dans le même ordre que la liste. Comment préférez-vous procéder?

  1. Lisez un nom dans 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'élève suivant ou la dernière page.
  5. Fermez le notebook.
  6. Répéter.

Ou:

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

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

jcollum
la source
3

Il a très certainement tort. Bien qu'il y ait des avantages indéniables à la manipulation de données dans des langages tels que C # ou Java, les jointures sont les plus rapides dans la base de données en raison de la nature même de SQL.

SQL continue de détailler les statistiques concernant les données, et si vous avez créé correctement vos index, vous pouvez 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 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 exécuter une fonction pour chaque ligne, il est probablement plus rapide de le faire dans C #, sinon, la jonction des données est optimisée dans la base de données.

Mike M.
la source
3

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'était qu'avec une seule version de MySQL que je devais 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).

JaCraig
la source
3

Je soupçonne qu'il a une vision limitée de l'utilisation des bases de données. Une approche pour maximiser les performances consiste à lire la base de données entière en mémoire. Dans cette situation, vous pouvez obtenir de meilleures performances et vous souhaiterez peut-être effectuer des jointures si la mémoire est efficace. Cependant, ce n'est pas vraiment en utilisant une base de données, comme une base de données à mon humble avis.

Peter Lawrey
la source
3
De toute façon, la plupart des moteurs de base de données le feront pour vous dans les coulisses; et par exemple dans MySQL, vous pouvez créer une table ( MEMORYmoteur) purement en mémoire . Ré-implémenter la fonctionnalité de base de données sans la base de données est généralement le signe d'un cas grave de NIH;)
Piskvor a quitté le bâtiment le
@phoog: Pas inventé ici - en d'autres termes, "Je n'y ai pas pensé, donc ça n'existe pas". De nombreuses roues carrées ont été réinventées à cause de cela. (et oui, il est parfois utile de réinventer la roue, par exemple si vous fabriquez des voitures de course; il est peu probable que réinventer «juste parce que» vous donne une meilleure roue)
Piskvor a quitté le bâtiment le
En d'autres termes, "je ne l'ai pas fait, donc ça doit être des ordures". Cela n'a un grain de vérité que dans la mesure où "Je ne l'ai pas testé, donc il pourrait ne pas convenir à mes besoins", donc testez-le avant de le juger.
Peter Lawrey
@Piskvor: Pas nécessairement, la base de données ne peut utiliser que la mémoire du système sur lequel elle s'exécute, alors que l'application peut utiliser la mémoire du serveur d'applications. En d'autres termes: si la base de données est sur un hôte dédié, l'accès à ce cache nécessite toujours une bande passante réseau et est soumis à une latence réseau, mais tout cache conservé par l'application peut être interrogé avec la vitesse d'une faible latence d'accès à la mémoire.
meriton
2

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

Jonas Byström
la source
2

Il a tort, les jointures sont ce que les programmeurs compétents utilisent. Il peut y avoir quelques cas limités où sa méthode proposée est plus efficace (et dans ceux-ci j'utiliserais probablement une base de données documant) mais je ne peux pas le voir si vous avez une quantité de données décevante. Par exemple, prenez cette requête:

select t1.field1 
from table1 t1
join table2 t2 
    on t1.id = t2.id
where t1.field2 = 'test'

Supposons que vous ayez 10 millions d'enregistrements dans la table1 et 1 million d'enregistrements dans la table2. Supposons que 9 millions d'enregistrements du tableau 1 satisfassent à la clause where. Supposons que seulement 15 d'entre eux figurent également dans le tableau 2. Vous pouvez exécuter cette instruction SQL qui, si elle est correctement indexée, prendra des millisecondes et renverra 15 enregistrements sur le réseau avec une seule colonne de données. Ou vous pouvez envoyer dix millions d'enregistrements avec 2 colonnes de données et envoyer séparément 1 million d'enregistrements supplémentaires avec une colonne de données sur le réseau et les combiner sur le serveur Web.

Ou bien sûr, vous pouvez conserver tout le contenu de la base de données sur le serveur Web à tout moment, ce qui est tout simplement ridicule si vous avez plus qu'une quantité insignifiante de données et de données en constante évolution. Si vous n'avez pas besoin des qualités d'une base de données relationnelle, n'en utilisez pas. Mais si vous le faites, utilisez-le correctement.

HLGEM
la source
2

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 a fait 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'elles sont mal utilisées , les jointures semblent inutiles, voire dangereuses. Mais lorsqu'il est utilisé correctement, il existe un grand potentiel pour l'implémentation de la base de données pour effectuer des optimisations et «aider» le développeur à récupérer le résultat correct le plus efficacement possible.

N'oubliez pas qu'en utilisant a, JOINvous indiquez à la base de données la manière dont vous vous attendez à ce que les éléments de données se rapportent les uns aux autres et donnez donc à la base de données plus d'informations sur ce que vous essayez de faire et par conséquent, en la rendant mieux adaptée à vos besoins.

La réponse est donc: non, JOINSne sont pas du tout inutiles!

perdian
la source
0

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 de la ou 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.

Fredt
la source
0

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

S'il y a 20 lignes dans B pour chaque A, 1000 lignes dans A impliquent 20k lignes dans B. .

Donc, pour obtenir toutes les informations sur 20 des 100 lignes B qui correspondent à chaque ligne A, vous tablez également AB. Donc ce serait soit:

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

Ainsi, "JOIN" dans le client ajoute une valeur quelconque 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 un seul.

Dans tous les 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 REJOINDRE quelque part, et c'est ce pour quoi les SGBDR sont bons. Je n'aimerais 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 jointure de base de données.

gbn
la source