2011-02-07 13 views
11

Un vecchio sistema è arrivato nel nostro ufficio per alcune modifiche e correzioni, ma soffre anche di problemi di prestazioni. Non sappiamo esattamente quale sia la fonte di questa lentezza.Cosa c'è di meglio? Sottoquery o inner join dieci tabelle?

Mentre stavamo refactoring del vecchio codice che abbiamo trovato diverse query SQL con il modello seguito (le query sono semplificate per esempio scopo):

SELECT 
    (
    SELECT X 
    FROM A 
    WHERE A.id = TABLE.id 
    ) AS COLUMN1, 
    (
    SELECT Y 
    FROM B 
    WHERE B.id = TABLE.id 
    ) AS COLUMN1, 
    (
    SELECT Z 
    FROM C 
    WHERE C.id = TABLE.id 
    ) AS COLUMN1, 
    ... 
FROM 
    TABLE 
WHERE 
    TABLE.id = @param; 

Queste query fanno diverse query sub interni da ogni colonna hanno ritorno.

stiamo pensando di riscrivere queste query sul modello seguito:

SELECT 
    A.X, B.Y, C.Z 
FROM 
    TABLE 
    INNER JOIN A on A.ID = TABLE.ID 
    INNER JOIN B on B.ID = TABLE.ID 
    INNER JOIN C on C.ID = TABLE.ID 
WHERE 
    TABLE.id = @param; 

Con inner join sono più facili da leggere e capire, ma è davvero più veloce? È il modo migliore per scriverli? Sfortunatamente il primo che abbiamo riscritto non ha migliorato il tempo di interrogazione, ha reso la query un po 'più lenta.

Ecco la mia domanda: dovremmo riscrivere tutte queste domande? Queste sottoquery sono un buon modo per fare questo lavoro? Sono più veloci nel modo interiore di unirsi?

+0

Tom (Kyte, di fama Oracle) ha dato una bella (e breve) risposta a una domanda molto simile qui: ["join vs subquery, clausola Exists"] (https://asktom.oracle.com/pls/asktom/f? p = 100: 11: 0 :::: P11_QUESTION_ID: 66812779016023) –

risposta

14

Se ho compreso correttamente la tua domanda, stai iniziando un'operazione per riscrivere alcune delle tue istruzioni SQL perché PENSI che ci possa essere un problema con loro.

Il mio consiglio è di fermarsi e iniziare a determinare dove è attualmente trascorso il tempo. Solo dopo aver scoperto che è nelle query con quelle sottoselezioni scalari E è a causa di quelle sottoselezioni scalari, dovresti riscriverle. Fino ad allora: iniziare a tracciare ed esaminare.

Qui ci sono due thread da OTN che vengono utilizzati per guidare le persone con problemi di prestazioni:

http://forums.oracle.com/forums/thread.jspa?messageID=1812597 http://forums.oracle.com/forums/thread.jspa?threadID=863295

saluti,
Rob.

E: a causa di scalar subquery caching, la query originale potrebbe essere molto più veloce di una query riscritta utilizzando i join.

+1

La tua risposta mi ha detto esattamente qualcosa su cui non ho parlato: "cache di subquery scalare". Forse le sottoquery possono essere buone a volte. Tuttavia, abbiamo riscritto un'altra query e ottenuto un risultato molto migliore, da 0,5 a 0,04 s. Sto firmando il tuo post come quello giusto perché per alcune persone le sottocommissioni potrebbero essere una buona soluzione. Grazie. –

7

la sottoquery viene effettivamente eseguita una volta per ogni riga mentre il join si verifica sugli indici.

Utilizzare i join per migliorare la leggibilità e la manutenibilità, come già menzionato nelle domande.

+0

Perché? se c'è un indice, dovrebbe essere applicato per una semplice ricerca di ID. –

+0

A volte la tabella non è unita dalle colonne indicizzate. Influisce sulla preferenza per l'inner join? –

+3

@ Adam, @ Gustavo - Le prestazioni dipendono dal motore del database su cui si stanno eseguendo le query. Devi controllare la performance usando il piano di esecuzione (non sei sicuro di quale esattamente si chiami in oracle). A volte le subquery sono migliori, a volte si uniscono, ma infine per una migliore leggibilità e per mantenere le query, i join hanno un leggero vantaggio. –

3

I join ti offriranno prestazioni migliori, ma ti consiglio di dare un'occhiata al piano di esecuzione ogni volta che "ottimizzi" le query.

+0

Dovrei tenere d'occhio il piano, grazie. Non c'è tunning reale senza misurare il risultato. –

2

Come this answer argues, è dovrebbe non influenzare la prestazione. Tuttavia, alcuni ottimizzatori di query potrebbero funzionare meglio su JOIN, quindi è consigliabile eseguire alcuni esperimenti sul sistema.

E ora qualcosa di completamente diverso: JOIN ing ogni tavolo per il prossimo potrebbe essere più estetico che JOIN ing tutte con TABLE, e previene gli errori ogni volta che l'id appare più di una volta in uno dei tavoli:

SELECT 
    A.X, B.Y, C.Z 
FROM 
    TABLE 
    INNER JOIN A on A.ID = TABLE.ID 
    INNER JOIN B on A.ID = B.ID 
    INNER JOIN C on B.ID = C.ID 
WHERE 
    TABLE.id = @param; 
+0

Grazie per l'esempio. Di sicuro è meglio leggere. Nel mio esempio ci sono solo 3 join, ma ogni query qui lo fa 10 o più volte per query ... –