Le iscrizioni sono per le persone pigre?


169

Di recente ho avuto una discussione con un altro sviluppatore che mi ha affermato che i JOIN (SQL) sono inutili. Ciò è tecnicamente vero, ma ha aggiunto che l'utilizzo dei join è meno efficiente rispetto a effettuare diverse richieste e collegare le tabelle nel codice (C # o Java).

Per lui i join sono per le persone pigre che non si preoccupano delle prestazioni. È vero? Dovremmo evitare di utilizzare i join?


114
No. I database sono ottimizzati per eseguire join, sono estremamente veloci soprattutto per set di dati di grandi dimensioni. Non si desidera che l'applicazione carichi decine di migliaia di righe e le unisca manualmente.
halfdan

91
I linguaggi di programmazione sono per le persone pigre; sono meno efficienti della codifica manuale delle istruzioni della CPU. :)
Michael McGowan,

76
Qual è il nome dello sviluppatore? Voglio assicurarmi di non assumerlo mai.
Joe,

39
@Michael meh, i veri programmatori usano le farfalle ...
Marc Gravell

14
Per quanto riguarda "questo è vero" - no, non lo è. I database funzionano tramite teoria degli insiemi; i set sul set funzionano in modo molto piacevole e utile ...
Marc Gravell

Risposte:


188

No, dovremmo evitare gli sviluppatori che hanno opinioni così incredibilmente sbagliate.

In molti casi, un join di database è più veloce di molti ordini di grandezza rispetto a qualsiasi altra operazione effettuata tramite il client, poiché evita i round trip del DB e il DB può utilizzare gli indici per eseguire il join.

In cima alla mia testa, non riesco nemmeno a immaginare un singolo scenario in cui un join usato correttamente sarebbe più lento dell'equivalente operazione lato client.

Modifica: ci sono alcuni rari casi in cui il codice client personalizzato può fare le cose in modo più efficiente di un semplice join DB (vedi commento di Meriton). Ma questa è davvero un'eccezione.


1
Che dire dei join a 3 vie? Non ci sono casi in cui faresti meglio a farli "in codice"?
julien_c,

56
L'adesione al server delle app può essere più efficiente se l'adesione al database provoca una grave ridondanza nel set di risultati inviato sulla rete. Considera le tabelle A e B, dove ogni riga in A è associata a 20 righe in B, B ha solo 100 righe e vogliamo recuperare le prime 1000 righe da A con le righe associate da B. L'unione nel database comporterà 20 * 1000 tuple inviate attraverso la rete. Se il join viene eseguito nel server delle app (prima recuperare l'intera tabella B in memoria), vengono inviate sulla rete solo 100 + 1000 righe.
meriton

7
Tuttavia, hai certamente ragione nel dire che i join nel database sono molto più veloci nella maggior parte dei casi, e quindi non solo una questione di convenienza, ma di necessità.
meriton

13
Ho avuto la fortuna di parlare con alcuni degli sviluppatori che lavorano su SQL Server in Microsoft. Ti farà venire le vertigini ascoltando le ottimizzazioni che fanno sulle query. Chiunque pensi di essere più intelligente di quello deve essere colpito.
riwalk

2
@meriton Sono un po 'sorpreso; Mi aspetto che la libreria client ottimizzi i join incrociati.
Phil Lello,

83

Mi sembra che il tuo collega farebbe bene con un database di documenti senza sql o un archivio di valori-chiave. Quali sono essi stessi ottimi strumenti e una buona misura per molti problemi.

Tuttavia, un database relazionale è fortemente ottimizzato per lavorare con i set. Esistono molti, molti modi di interrogare i dati basati sui join che sono molto più efficienti di molti round trip. Ecco da dove viene la versatilità di un rdbms. Puoi ottenere lo stesso anche in un negozio nosql, ma spesso finisci per costruire una struttura separata adatta a ogni diversa natura della query.

In breve: non sono d'accordo. In un RDBMS, i join sono fondamentali . Se non li stai usando, non lo stai usando come RDBMS.


46

Bene, ha torto nel caso generale.

I database sono in grado di ottimizzare utilizzando una varietà di metodi, aiutati da suggerimenti per l'ottimizzazione, indici delle tabelle, relazioni con le chiavi esterne e possibilmente altre informazioni specifiche del fornitore del database.


1
Devo ammettere che quando ho iniziato a lavorare con i database avevo la stessa convinzione di poter battere le prestazioni dei join. Ma non ci è voluto molto tempo per rendersi conto di quanto incredibilmente veloci sono i join del DB. In effetti direi che in questa situazione è meglio discuterne apertamente con il dipendente piuttosto che liquidarlo come un idiota.
LegendLength

1
@LegendLength Direi che è anche vero se non sono così intelligenti. Non c'è bisogno di assumere intelligenza perché fanno gli stessi errori che ricordiamo di aver fatto (in effetti, per me ciò potrebbe significare che non sono così intelligenti ...) È più semplice: raramente aiuta a essere sprezzanti. Va bene sbagliarsi, una volta ogni tanto!
Sehe

24

No, non dovresti.

I database sono appositamente progettati per manipolare insiemi di dati (ovviamente ....). Pertanto sono incredibilmente efficienti nel fare questo. Facendo quello che è essenzialmente un join manuale nel proprio codice, sta cercando di assumere il ruolo di qualcosa di specificamente progettato per il lavoro. Le possibilità che il suo codice sia sempre efficiente come quello nel database sono molto remote.

Per inciso, senza join, qual è il punto di usare un database? può anche usare solo file di testo.


2
Anche senza unirsi? Mappatura automatica in memoria, memorizzazione automatica delle query nella cache, molte altre cose automagic che non si verificano affatto con la maggior parte dei filesystem. Oh, ho già parlato di transazioni controllabili con precisione?
Piskvor lasciò l'edificio l'

19

Se "pigro" è definito come persone che vogliono scrivere meno codice, allora sono d'accordo. Se "pigro" è definito come le persone che vogliono avere strumenti che fanno ciò che sono bravi a fare, sono d'accordo. Quindi, se è semplicemente d'accordo con Larry Wall (riguardo agli attributi di buoni programmatori), allora sono d'accordo con lui.


Ho aggiunto la precisione di pigro: per le persone pigre che non si preoccupano delle prestazioni e preferiscono scrivere meno codice. Penso che i join siano per le persone pigre, ma in questo caso anche i join sono migliori di diverse richieste.
Bastien Vandamme,

3
@Dran Dane: i join sono per i più pigri, sì. Il fatto che probabilmente funzioneranno bene è ortogonale.
Piskvor lasciò l'edificio l'

16

Ummm, join è il modo in cui i database relazionali mettono in relazione le tabelle tra loro. Non sono sicuro di cosa stia arrivando.

In che modo effettuare più chiamate al database può essere più efficiente di una chiamata? Inoltre i motori sql sono ottimizzati per fare questo genere di cose.

Forse il tuo collega è troppo pigro per imparare l'SQL.


12

Si, dovresti.

E dovresti usare C ++ invece di C # a causa delle prestazioni. C # è per le persone pigre.

No, no, no. Dovresti usare C invece di C ++ a causa delle prestazioni. C ++ è per le persone pigre.

No, no, no. Dovresti usare assembly invece di C a causa delle prestazioni. C è per le persone pigre.

Sì, sto scherzando. puoi creare programmi più veloci senza join e puoi creare programmi usando meno memoria senza join. MA in molti casi, il tempo di sviluppo è più importante del tempo e della memoria della CPU. Rinuncia a una piccola esibizione e goditi la vita. Non perdere tempo per piccole piccole prestazioni. E digli "Perché non fai un'autostrada diritta da casa tua al tuo ufficio?"


1
Finora ho esaminato tutte le tue risposte e sono molto divertenti. Per favore, continua a venire. O quello o, dove posso iscrivermi al tuo blog?
Gerry,

11

"Questo è tecnicamente vero" - allo stesso modo, un database SQL è inutile: qual è il punto di usarne uno quando puoi ottenere lo stesso risultato usando un mucchio di file CSV e correlandoli nel codice? Diamine, qualsiasi astrazione è per le persone pigre, torniamo alla programmazione in codice macchina direttamente sull'hardware! ;)

Inoltre, la sua affermazione non è vera in tutti tranne nei casi più contorti: gli RDBMS sono fortemente ottimizzati per rendere i JOIN veloci . Sistemi di gestione di database relazionali , giusto?


2
+1 La frase "... tecnicamente vero" avrebbe funzionato meglio se l'OP avesse usato la parola unnecessarypiuttosto uselessnella frase precedente. Dire che i join sono inutili è palesemente falso, senza tecnicismi che richiedono considerazione. In ogni caso, l'equivoco del collega del punto di RDBMS del PO ed è sandly non è raro: stackoverflow.com/q/5575682/47550
Paul Sasik

7

L'ultima società per cui ho lavorato non ha utilizzato neanche i join SQL. Invece hanno spostato questo lavoro a livello di applicazione che è progettato per ridimensionare orizzontalmente. La logica di questo progetto è di evitare il lavoro a livello di database. Di solito è il database che diventa collo di bottiglia. È più facile replicare il livello applicazione rispetto al database. Potrebbero esserci altri motivi. Ma questo è quello che posso ricordare ora.

Sì, sono d'accordo che i join eseguiti a livello di applicazione sono inefficienti rispetto ai join eseguiti dal database. Più comunicazione di rete anche.

Si noti che non sto prendendo una posizione dura per evitare i join SQL.


Bene, sembra un argomento razionale nei confronti di JOIN nel tuo caso specifico. Ricordo che FB Engineering ha pubblicato qualcosa di simile sul loro blog: il ridimensionamento era anche la loro priorità chiave. Purtroppo, solo un piccolo% dei programmatori dovrà mai farlo, ma molti pensano di farlo "perché anche OMG Facebook lo fa";)
Piskvor ha lasciato l'edificio l'

va bene, in una soluzione aziendale in cui hai abbastanza traffico per sovraccaricare il server di database, questo può valere la pena di essere preso in considerazione, ma è più probabile che si tratti della procedura memorizzata di reporting o del backup pianificato che inchioda le prestazioni. I database sono bravi a partecipare, specialmente se ci sono indecie che aiutano
Jodrell

@Jodrell: Sì, sono bravi a partecipare; di nuovo, ci sono casi angolari in cui è necessario abbandonare l'eleganza dei join per ottenere più potenza. Ho incontrato una di queste situazioni; abbiamo provato ogni possibile soluzione, e in effetti una soluzione senza join è stata la più veloce in quella situazione molto specifica . E no, non c'era nient'altro che funzionasse su quel particolare server; le procedure memorizzate non possono rallentarti se non ne hai;)
Piskvor ha lasciato l'edificio l'

5

Senza join come hai intenzione di mettere in relazione gli articoli con gli ordini? Questo è l'intero punto di un sistema di gestione di database relazionali. Senza join non ci sono dati relazionali e potresti anche usare file di testo per elaborare i dati.

Sembra che non capisca il concetto, quindi sta cercando di far sembrare che siano inutili. È lo stesso tipo di persona che pensa che Excel sia un'applicazione di database. Slapalo sciocco e digli di leggere di più sui database. Effettuare connessioni multiple, estrarre dati e unire i dati tramite C # è il modo sbagliato di fare le cose.


5

Non capisco la logica dell'istruzione "i join in SQL sono inutili". È utile filtrare e limitare i dati prima di lavorarci? Come altri intervistati hanno affermato, questo è ciò che fanno i motori di database, dovrebbe essere ciò in cui sono bravi.

Forse un programmatore pigro si atterrebbe alle tecnologie con cui era familiare e avrebbe evitato altre possibilità per ragioni non tecniche.

Lascio a te decidere.


5

Consideriamo un esempio: una tabella con i record delle fatture e una tabella correlata con i record degli elementi pubblicitari delle fatture. Considera lo pseudo codice client:

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

Se hai 100.000 fatture con 10 righe ciascuna, questo codice cercherà 10 righe di fattura da una tabella di 1 milione e lo farà 100.000 volte. All'aumentare della dimensione della tabella, aumenta il numero di operazioni di selezione e aumenta il costo di ciascuna operazione di selezione.

Poiché i computer sono veloci, potresti non notare una differenza di prestazioni tra i due approcci se ne hai diverse migliaia o meno. Poiché l'aumento dei costi è più che lineare, all'aumentare del numero di record (in milioni, diciamo), inizierai a notare una differenza e la differenza diventerà meno tollerabile con l'aumentare delle dimensioni del set di dati.

Il join, tuttavia. utilizzerà gli indici della tabella e unirà i due set di dati. Ciò significa che stai effettivamente scansionando la seconda tabella una volta anziché accedervi casualmente N volte. Se è stata definita una chiave esterna, il database ha già i collegamenti tra i record correlati memorizzati internamente.

Immagina di farlo da solo. Hai un elenco alfabetico di studenti e un quaderno con tutti i rapporti dei voti degli studenti (una pagina per classe). Il taccuino è ordinato in base ai nomi degli studenti, nello stesso ordine dell'elenco. Come preferiresti procedere?

  1. Leggi un nome dall'elenco.
  2. Apri il quaderno.
  3. Trova il nome dello studente.
  4. Leggi i voti dello studente, girando le pagine fino a raggiungere lo studente successivo o l'ultima pagina.
  5. Chiudi il quaderno.
  6. Ripetere.

O:

  1. Apri il blocco note alla prima pagina.
  2. Leggi un nome dall'elenco.
  3. Leggi tutti i voti per quel nome dal taccuino.
  4. Ripeti i passaggi 2-3 fino alla fine
  5. Chiudi il quaderno.

5

Sembra un classico caso di " Posso scriverlo meglio ". In altre parole, sta vedendo qualcosa che vede come una specie di dolore al collo (scrivendo un sacco di join in SQL) e dicendo "Sono sicuro di poterlo scrivere meglio e ottenere prestazioni migliori". Dovresti chiedergli se è a) più intelligente eb) più istruito rispetto alla persona tipica che è al ginocchio nel codice di ottimizzazione di Oracle o SQL Server. Le probabilità sono che non lo sia.


3

Sicuramente ha torto. Mentre ci sono pro definiti per la manipolazione dei dati all'interno di linguaggi come C # o Java, i join sono i più veloci nel database a causa della natura dello stesso SQL.

SQL continua a dettagliare le statistiche relative ai dati e, se gli indici sono stati creati correttamente, è possibile trovare molto rapidamente un record su un paio di milioni. Oltre al fatto che perché dovresti voler trascinare tutti i tuoi dati in C # per fare un join quando puoi semplicemente farlo a livello di database?

I professionisti dell'utilizzo di C # entrano in gioco quando devi fare qualcosa in modo iterativo. Se è necessario eseguire alcune funzioni per ogni riga, è probabilmente più veloce farlo in C #, altrimenti l'unione dei dati è ottimizzata nel DB.


3

Dirò che mi sono imbattuto in un caso in cui è stato più veloce abbattere la query e fare i join nel codice. Detto questo, è stato solo con una versione particolare di MySQL che ho dovuto farlo. Tutto il resto, il database probabilmente sarà più veloce (tieni presente che potresti dover ottimizzare le query, ma sarà comunque più veloce).


3

Ho il sospetto che abbia una visione limitata su quali database dovrebbero essere usati. Un approccio per massimizzare le prestazioni è leggere l'intero database in memoria. In questa situazione, potresti ottenere prestazioni migliori e potresti voler eseguire join se memoria per efficienza. Tuttavia, questo non utilizza realmente un database, come IMHO di database.


3
La maggior parte dei motori di database lo farà comunque dietro le quinte; e ad esempio in MySQL è possibile creare una tabella ( MEMORYmotore) puramente in memoria . La reimplementazione della funzionalità del database senza il database è di solito un segno di un grave caso di NIH;)
Piskvor ha lasciato l'edificio l'

@phoog: non inventato qui - in altre parole, "Non ci ho pensato, quindi non esiste". Molte ruote quadrate sono state reinventate per questo. (e sì, a volte reinventare la ruota è utile, ad esempio se stai costruendo auto da corsa; reinventare "solo perché" è improbabile che ti
dia

In altre parole, "non ce l'ho fatta, quindi deve essere spazzatura". Questo ha un granello di verità solo nella misura in cui "Non l'ho provato, quindi potrebbe non essere adatto ai miei scopi", quindi provalo prima di giudicarlo.
Peter Lawrey,

@Piskvor: non necessariamente, il database può usare solo la memoria del sistema su cui gira, mentre l'applicazione può usare la memoria del server delle applicazioni. In altre parole: se il database si trova su un host dedicato, l'accesso a quella cache richiede ancora una connessione di banda di rete ed è soggetto alla latenza di rete, ma qualsiasi cache conservata dall'applicazione può essere interrogata con la velocità a bassa latenza dell'accesso alla memoria.
Meriton,

2

No, non solo i join sono ottimizzati meglio nel codice del database che C # / Java ad hoc; ma di solito possono essere applicate diverse tecniche di filtraggio, che offrono prestazioni ancora migliori.


2

Ha torto, i join sono ciò che usano i programmatori competenti. Potrebbero esserci alcuni casi limitati in cui il suo metodo proposto è più efficiente (e in quel caso probabilmente utilizzerei un database Documant) ma non riesco a vederlo se hai una quantità ingannevole di dati. Ad esempio, prendi questa query:

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

Supponiamo di avere 10 milioni di record nella tabella1 e 1 milione di record nella tabella2. Supponiamo che 9 milioni dei record nella tabella 1 soddisfino la clausola where. Supponiamo che solo 15 di loro siano nella tabella2. È possibile eseguire questa istruzione sql che, se correttamente indicizzata, richiederà millisecondi e restituisce 15 record attraverso la rete con solo 1 colonna di dati. Oppure puoi inviare dieci milioni di record con 2 colonne di dati e inviare separatamente altri 1 milione di record con una colonna di dati attraverso la rete e combinarli sul server Web.

O ovviamente potresti tenere sempre l'intero contenuto del database sul web server, il che è semplicemente stupido se hai più di una banale quantità di dati e dati che cambiano continuamente. Se non sono necessarie le qualità di un database relazionale, non utilizzarne uno. Ma se lo fai, quindi usalo correttamente.


2

Ho sentito questo argomento abbastanza spesso durante la mia carriera come sviluppatore di software. Quasi ogni volta che è stato affermato, il ragazzo che ha fatto la richiesta non aveva molta conoscenza dei sistemi di database relazionali, del modo in cui funzionano e del modo in cui tali sistemi dovrebbero essere utilizzati.

Sì, se usato in modo errato , i join sembrano essere inutili o addirittura pericolosi. Tuttavia, se utilizzato nel modo corretto, l'implementazione del database ha molte potenzialità per eseguire ottimizzazioni e "aiutare" lo sviluppatore a recuperare il risultato corretto nel modo più efficiente.

Non dimenticare che l'utilizzo di a JOINindica al database il modo in cui ti aspetti che i dati si relazionino tra loro e quindi fornisci al database maggiori informazioni su ciò che stai cercando di fare e rendendolo quindi in grado di adattarsi meglio alle tue esigenze.

Quindi la risposta è sicuramente: No, JOINSnon sono affatto inutile!


0

Ciò è "tecnicamente vero" solo in un caso che non viene utilizzato spesso nelle applicazioni (quando tutte le righe di tutte le tabelle nei join vengono restituite dalla query). Nella maggior parte delle query viene restituita solo una frazione delle righe di ogni tabella. Il motore di database utilizza spesso gli indici per eliminare le righe indesiderate, a volte anche senza leggere la riga effettiva in quanto può utilizzare i valori memorizzati negli indici. Il motore di database stesso è scritto in C, C ++, ecc. Ed è almeno efficiente quanto il codice scritto da uno sviluppatore.


0

A meno che non abbia seriamente frainteso, la logica della domanda è molto imperfetta

Se ci sono 20 righe in B per ogni A, 1000 righe in A implicano 20k righe in B. Non ci possono essere solo 100 righe in B a meno che non ci siano molte tabelle "AB" con 20k righe con il contenimento della mappatura .

Quindi, per ottenere tutte le informazioni su quale 20 delle 100 righe di B mappano su ciascuna riga A, anche la tabella AB. Quindi questo sarebbe o:

  • 3 set di risultati di 100, 1000 e 20k righe e un client JOIN
  • un singolo set di risultati A-AB-B JOINed con 20k righe

Quindi "JOIN" nel client aggiunge alcun valore quando si esaminano i dati. Non che non sia una cattiva idea. Se stavo recuperando un oggetto dal database di quanto forse abbia più senso suddividerlo in set di risultati separati. Per una chiamata del tipo di rapporto, la appiattirei in una quasi sempre.

In ogni caso, direi che non serve quasi a un cross join di questa portata. È un cattivo esempio.

Devi ISCRIVERSI da qualche parte, ed è ciò che RDBMS è bravo a fare. Non mi piacerebbe lavorare con nessuna scimmia di codice client che pensa di poter fare di meglio.

Ripensamento:

Per aderire al client sono necessari oggetti persistenti come DataTables (in .net). Se hai un set di risultati appiattito, può essere consumato tramite qualcosa di più leggero come un DataReader. Volume elevato = molte risorse client utilizzate per evitare un database JOIN.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.