Utilizzare una query che recupera dati ridondanti da tabelle collegate o più query e unirli nel codice?

2

Ho tre tabelle con una catena di due relazioni uno-a-molti. Ci sono due modi in cui posso pensare di recuperare i dati in base alla chiave primaria della prima tabella.

  1. JOIN ogni tabella (o LEFT JOIN se ci sono righe inesistenti) in una singola query ( SELECT * FROM t1, t2, t3 WHERE t1.id = 123 AND t2.t1_id = t1.id AND t3.t2_id = t2.id )
  2. Esegui tre query che collegano ogni volta alla chiave primaria della prima tabella ( SELECT t3.* FROM t3, t2, t1 WHERE t3.t2_id = t2.id AND t2.t1_id = t1.id AND t1.id = 123 ). Mantieni aperta la connessione al database finché i dati non sono stati ricevuti da tutte e tre le tabelle

Usando un singolo JOIN restituirai dati ridondanti e dovrai gestire il caso speciale quando ci sono zero righe sul lato destro separatamente. L'esecuzione di tre query implica che il motore del database dovrà eseguire operazioni molto simili per tre volte e potrebbe aumentare la latenza. È possibile dire quale è "migliore"? Dipende dalla situazione, ad es. la dimensione dei dati da recuperare è il database sullo stesso server / rete del codice chiamante, ecc.?

    
posta CJ Dennis 08.07.2016 - 02:44
fonte

2 risposte

4

Questo tipo di domande non possono essere risolte in modo ragionevole a livello astratto, senza il contesto circostante. Devi provare questo utilizzando il sistema reale : un vero database, pieno di dati reali, una rete reale, una vera macchina client che esegue un'applicazione reale client.

Quindi sarà possibile profilo entrambi gli approcci e confrontarli. E tieni presente che le prestazioni potrebbero non essere l'unico e nemmeno il fattore principale per prendere la decisione da scegliere. Ad esempio, se la tua prima query risulta essere più lenta, ma la seconda mantiene il codice client più semplice ed è abbastanza veloce per il tuo caso d'uso (o viceversa), dovresti probabilmente scegliere la soluzione più semplice.

Se vuoi una raccomandazione da realizzare prima: inizia con la soluzione che "senti" rende più semplice il codice (codice client SQL + in totale). Ottimizza solo se risulta che non è abbastanza veloce per il tuo caso d'uso.

    
risposta data 08.07.2016 - 07:36
fonte
1

Dovresti usare i join e limitare le colonne selezionate, ed eseguire più selezioni nella singola query: (cambia leggermente la struttura per ridurre il codice di esempio)

SELECT t1.* FROM 
    t1
LEFT JOIN
    t2
    on t2.t1_id = t1.id 
WHERE 
    t1.id > 123 and t1.id < 321;

SELECT t2.* FROM 
    t1
INNER JOIN
    t2
    on t2.t1_id = t1.id 
WHERE 
    t1.id > 123 and t1.id < 321;

Il tuo codice può quindi iterare il primo set di dati per popolare i t1s e il secondo set di dati aggiungendo i figli alla corretta ora nella memoria t1 oggetto

Dictionary<string,t1> t1s;
foreach(var t1 in dataSet1)
{
    t1s.Add(t1.Id, t1);
}
foreach(var t2 in dataSet2)
{
    t1s[t2.t1id].Childern.Add(t2);
}

L'SQL può essere ottimizzato con tabelle temporanee ecc. se necessario.

Questo offre solo prestazioni leggermente migliori rispetto all'esecuzione separata delle due query. Fornendo che la tua query figlio abbia la forma 'dove t2.t1Id si trova in {1,2,3,4,5 ..)' invece di essere ripetuta per id

    
risposta data 08.07.2016 - 12:01
fonte

Leggi altre domande sui tag