PARTECIPA query o più query

Le query JOIN sono più veloci di alcune query? (Esegui la query principale, quindi esegui molti altri SELECT in base ai risultati della query principale)

Ti sto chiedendo perché unirti a loro complicherebbe MOLTO il design della mia applicazione

Se sono più veloci, qualcuno può approssimare approssimativamente da quanto? Se è 1.5x non mi interessa, ma se è 10x credo di sì.

Questo è troppo vago per darti una risposta pertinente al tuo caso specifico. Dipende da molte cose. Jeff Atwood (il fondatore di questo sito) in realtà ha scritto su questo . Per la maggior parte, però, se si hanno gli indici giusti e si fanno correttamente i JOIN, di solito è più veloce fare un viaggio di diversi.

Per i join interni, una singola query ha senso poiché si ottengono solo righe corrispondenti. Per i join di sinistra, più query sono molto meglio … guarda il seguente benchmark che ho fatto:

  1. Query singola con 5 join

    query: 8.074508 secondi

    dimensione del risultato: 2268000

  2. 5 domande di seguito

    tempo di query combinato: 0,00262 secondi

    dimensione del risultato: 165 (6 + 50 + 7 + 12 + 90)

.

Si noti che otteniamo gli stessi risultati in entrambi i casi (6 x 50 x 7 x 12 x 90 = 2268000)

i join di sinistra utilizzano in modo esponenziale più memoria con dati ridondanti.

Il limite di memoria potrebbe non essere così negativo se si esegue solo un join di due tabelle, ma in genere tre o più e diventa una query diversa.

Come nota a margine, il mio server MySQL è proprio accanto al mio server delle applicazioni … quindi i tempi di connessione sono trascurabili. Se il tempo di connessione è nei secondi, allora forse c’è un vantaggio

Franco

In realtà sono arrivato a questa domanda cercando una risposta da solo, e dopo aver letto le risposte date posso solo convenire che il modo migliore per confrontare le prestazioni delle query DB è ottenere numeri reali perché ci sono solo molte variabili da tenere in considerazione MA, penso anche che il confronto tra i numeri non porti a nulla in quasi tutti i casi. Quello che voglio dire è che i numeri dovrebbero sempre essere confrontati con un numero accettabile e sicuramente non confrontati l’uno con l’altro.

Posso capire se un modo di interrogare richiede 0,02 secondi e l’altro impiega 20 secondi, questa è un’enorme differenza. Ma cosa succede se un modo di interrogare richiede 0.0000000002 secondi e l’altro richiede 0.0000002 secondi? In entrambi i casi, un modo è incredibilmente 1000 volte più veloce dell’altro, ma nel secondo caso è davvero “enorme”?

In conclusione, personalmente, lo vedo: se funziona bene, scegli la soluzione facile.

Ha effettuato un test rapido selezionando una riga da una tabella di 50.000 righe e unendo una riga da una tabella di 100.000 righe. Fondamentalmente sembrava:

$id = mt_rand(1, 50000); $row = $db->fetchOne("SELECT * FROM table1 WHERE id = " . $id); $row = $db->fetchOne("SELECT * FROM table2 WHERE other_id = " . $row['other_id']); 

vs

 $id = mt_rand(1, 50000); $db->fetchOne("SELECT table1.*, table2.* FROM table1 LEFT JOIN table1.other_id = table2.other_id WHERE table1.id = " . $id); 

Il metodo di due selezioni ha impiegato 3,7 secondi per 50.000 letture mentre il JOIN ha impiegato 2,0 secondi sul mio computer lento a casa. INNER JOIN e LEFT JOIN non hanno fatto la differenza. Il recupero di più righe (ad esempio, utilizzando IN SET) ha prodotto risultati simili.

Costruisci sia query separate che join, quindi dedica il tempo a ciascuna di esse: nulla aiuta più dei numeri del mondo reale.

Allora ancora meglio – aggiungi “EXPLAIN” all’inizio di ogni query. Questo ti dirà quante subquery MySQL sta usando per rispondere alla tua richiesta di dati, e quante righe sono state scansionate per ogni query.

A seconda della complessità del database rispetto alla complessità degli sviluppatori, potrebbe essere più semplice eseguire molte chiamate SELECT.

Prova a eseguire alcune statistiche del database sia sul JOIN che sui SELEZIONATI multipli. Controlla se nel tuo ambiente il JOIN è più veloce / lento di SELECT.

Poi di nuovo, se cambiarlo in un JOIN significherebbe un giorno / settimana / mese in più di lavoro di sviluppo, rimango con più SELECTs

Saluti,

BLT

La vera domanda è: questi record hanno una relazione uno-a-uno o una relazione uno-a-molti ?

Risposta TLDR:

Se uno a uno, utilizzare una dichiarazione JOIN .

Se uno-a-molti, utilizzare una (o più) istruzioni SELECT con ottimizzazione del codice lato server.

Perché e come utilizzare SELECT per l’ottimizzazione

SELECT ‘ing (con più query invece di join) su un grande gruppo di record basato su una relazione uno-a-molti produce un’efficienza ottimale, poiché JOIN ‘ ha un problema di perdita di memoria esponenziale. Prendi tutti i dati, quindi usa un linguaggio di scripting sul lato server per risolverlo:

 SELECT * FROM Address WHERE Personid IN(1,2,3); 

risultati:

 Address.id : 1 // First person and their address Address.Personid : 1 Address.City : "Boston" Address.id : 2 // First person's second address Address.Personid : 1 Address.City : "New York" Address.id : 3 // Second person's address Address.Personid : 2 Address.City : "Barcelona" 

Qui, sto ottenendo tutti i record, in una dichiarazione selezionata. Questo è meglio di JOIN , che otterrebbe un piccolo gruppo di questi record, uno alla volta, come sottocomponente di un’altra query. Poi lo analizzo con il codice lato server che assomiglia a qualcosa …

 < ?php foreach($addresses as $address) { $persons[$address['Personid']]->Address[] = $address; } ?> 

Quando non usare JOIN per l’ottimizzazione

L’unione di un ampio gruppo di record basati su una relazione uno-a-uno con un singolo record produce un’efficienza ottimale rispetto a più istruzioni SELECT , una dopo l’altra, che ottengono semplicemente il tipo di record successivo.

Ma JOIN è inefficiente quando si ottengono record con una relazione uno-a-molti.

Esempio: il database Blog ha 3 tabelle di interesse, Blogpost, Tag e Comment.

 SELECT * from BlogPost LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id; 

Se c’è 1 blogpost, 2 tag e 2 commenti, otterrai risultati come:

 Row1: tag1, comment1, Row2: tag1, comment2, Row3: tag2, comment1, Row4: tag2, comment2, 

Nota come ogni record è duplicato. Ok, quindi, 2 commenti e 2 tag sono 4 righe. Cosa succede se abbiamo 4 commenti e 4 tag? Non ottieni 8 righe: ottieni 16 righe:

 Row1: tag1, comment1, Row2: tag1, comment2, Row3: tag1, comment3, Row4: tag1, comment4, Row5: tag2, comment1, Row6: tag2, comment2, Row7: tag2, comment3, Row8: tag2, comment4, Row9: tag3, comment1, Row10: tag3, comment2, Row11: tag3, comment3, Row12: tag3, comment4, Row13: tag4, comment1, Row14: tag4, comment2, Row15: tag4, comment3, Row16: tag4, comment4, 

Aggiungi più tabelle, più record, ecc. E il problema si gonfierà rapidamente in centinaia di file che sono tutte piene di dati per lo più ridondanti.

Cosa ti costano questi duplicati? Memoria (nel server SQL e nel codice che tenta di rimuovere i duplicati) e risorse di rete (tra il server SQL e il server di codice).

Fonte: https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html

Nella mia esperienza ho scoperto che di solito è più veloce eseguire diverse query, specialmente quando si recuperano insiemi di dati di grandi dimensioni.

Quando si interagisce con il database da un’altra applicazione, come PHP, c’è l’argomento di un trip sul server su molti.

Esistono altri modi per limitare il numero di viaggi effettuati sul server ed eseguire ancora più query che spesso non solo sono più veloci, ma rendono anche l’applicazione più facile da leggere, ad esempio mysqli_multi_query.

Non sono un principiante quando si tratta di SQL, penso che ci sia una tendenza per gli sviluppatori, in particolare i juniores, a dedicare molto tempo a scrivere join molto intelligenti perché sembrano intelligenti, mentre ci sono in realtà modi intelligenti per estrarre dati che sembrano semplice.

L’ultimo paragrafo è stato un parere personale, ma spero che questo aiuti. Sono d’accordo con gli altri, anche se chi dice che si dovrebbe fare un punto di riferimento. Nessuno dei due è un proiettile d’argento.

Sarà più veloce in termini di produttività? Probabilmente. Ma potenzialmente blocca anche più oggetti di database alla volta (a seconda del database e dello schema) e quindi diminuisce la concorrenza. Nella mia esperienza, le persone sono spesso fuorviate dall’argomento “un minor numero di round-trips di database” quando in realtà sulla maggior parte dei sistemi OLTP in cui il database si trova sulla stessa LAN, il vero collo di bottiglia è raramente la rete.

Ecco un collegamento con 100 query utili, queste sono testate nel database Oracle ma ricorda che SQL è uno standard, ciò che differisce tra Oracle, MS SQL Server, MySQL e altri database sono il dialetto SQL:

http://javaforlearn.com/100-sql-queries-learn/

Ci sono diversi fattori che indicano che non esiste una risposta binaria. La domanda su cosa è meglio per le prestazioni dipende dal tuo ambiente. A proposito, se la tua singola selezione con un identificatore non è inferiore al secondo, qualcosa potrebbe essere sbagliato con la tua configurazione.

La vera domanda da porsi è come si desidera accedere ai dati. La selezione singola supporta il late-binding. Ad esempio se si desidera solo informazioni sui dipendenti, è ansible selezionare dalla tabella Impiegati. Le relazioni con le chiavi esterne possono essere utilizzate per recuperare le risorse correlate in un momento successivo e secondo necessità. I selettivi avranno già una chiave da evidenziare, quindi dovrebbero essere estremamente veloci e devi solo recuperare ciò di cui hai bisogno. La latenza della rete deve essere sempre presa in considerazione.

I join recupereranno tutti i dati contemporaneamente. Se stai generando un report o compilando una griglia, questo potrebbe essere esattamente ciò che desideri. I join compilati e optomizzati saranno semplicemente più veloci dei single select in questo scenario. Ricorda che i join ad-hoc potrebbero non essere altrettanto veloci: dovresti compilarli (in un processo memorizzato). La velocità di risposta dipende dal piano di esecuzione, che descrive esattamente i passaggi che il DBMS impiega per recuperare i dati.

Sì, una query utilizzando JOINS sarebbe più veloce. Sebbene senza conoscere le relazioni delle tabelle che stai interrogando, le dimensioni del set di dati o le chiavi primarie, è quasi imansible dire quanto più velocemente.

Perché non testare entrambi gli scenari, allora lo saprai di sicuro …

Indipendentemente dal fatto che si debba utilizzare un join, è importante sapere se un join ha senso . Solo a quel punto le prestazioni sono qualcosa da considerare, poiché quasi tutti gli altri casi si traducono in prestazioni significativamente peggiori .

Le differenze di prestazioni saranno in gran parte legate al modo in cui sono correlate le informazioni per le quali stai interrogando. I join funzionano e sono veloci quando i dati sono correlati e indicizzano le cose correttamente, ma spesso determinano ridondanza e talvolta più risultati del necessario. E se i tuoi set di dati non sono direttamente correlati, inserirli in una singola query darà come risultato un prodotto cartesiano (in pratica tutte le combinazioni possibili di righe), che non è quasi mai quello che desideri.

Questo è spesso causato da relazioni molte-a-uno-molti. Ad esempio, la risposta di HoldOffHunger ha menzionato una singola query per post, tag e commenti. I commenti sono relativi a un post, così come i tag … ma i tag non sono correlati ai commenti.

 +------------+ +---------+ +---------+ | comment | | post | | tag | |------------|* 1|---------|1 *|---------| | post_id |-----| post_id |-----| post_id | | comment_id | | ... | | tag_id | | user_id | | | | ... | | ... | | | | ... | +------------+ +---------+ +---------+ 

In questo caso, è inequivocabilmente meglio per questo essere almeno due query separate. Se provi ad unire tag e commenti, perché non esiste una relazione diretta tra i due, finisci con ogni ansible combinazione di tag e commenti. many * many == manymany . A parte questo, poiché i post e i tag non sono correlati, puoi eseguire queste due query in parallelo, portando a un potenziale guadagno.

Consideriamo uno scenario diverso, tuttavia: desideri che i commenti siano allegati a un post e le informazioni di contatto dei commentatori.

  +----------+ +------------+ +---------+ | user | | comment | | post | |----------|1 *|------------|* 1|---------| | user_id |-----| post_id |-----| post_id | | username | | user_id | | ... | | ... | | ... | +---------+ +----------+ +------------+ 

Questo è dove si dovrebbe prendere in considerazione un join. Oltre ad essere una query molto più naturale, la maggior parte dei sistemi di database (incluso MySQL) hanno un sacco di persone intelligenti che fanno un sacco di duro lavoro per ottimizzare le query proprio come. Per query separate, poiché ogni query dipende dai risultati della precedente, le query non possono essere eseguite in parallelo e il tempo totale non diventa solo il tempo di esecuzione effettivo delle query, ma anche il tempo impiegato a recuperare i risultati, setacciando attraverso di loro per gli ID per la prossima query, collegando le righe insieme, ecc.