Oracle Joins – Confronto tra syntax convenzionale VS ANSI Sintassi

Preambolo

Di recente, vedo troppi fanatici che commentano le domande di Oracle che dicono che “Non usare l’operatore (+), piuttosto usa la syntax JOIN”.

Domanda

Vedo che entrambi funzionano bene. Ma qual è la vera differenza tra usarli e cosa ti fa sentire usarli? Vorrei ricevere risposte, più dall’esperienza.

1. Is there anything to do with limitations in application, performance, etc. while using them? 2. What would you suggest for me? 

Ho letto qualcosa sulla documentazione di Oracle, ma non abbastanza per farmi capire o sentirmi a mio agio con le informazioni complete.

    Nota : sto pianificando la migrazione di oltre 200 pacchetti e procedure, se la parola chiave deve essere utilizzata al posto di (+)

      3. Also is there any freeware tools to do the rewrite? 

    Pubblicare campioni

     ┌───────────────────────────────────┬─────────────────────────────────────────────┐ │ INNER JOIN - CONVENTIONAL │ INNER JOIN - ANSI SYNTAX │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ SELECT │ SELECT │ │ emp.deptno │ ename, │ │ FROM │ dname, │ │ emp, │ emp.deptno, │ │ dept │ dept.deptno │ │ WHERE │ FROM │ │ emp.deptno = dept.deptno; │ scott.emp INNER JOIN scott.dept │ │ │ ON emp.deptno = dept.deptno; │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ LEFT OUTER JOIN - CONVENTIONAL │ LEFT OUTER JOIN - ANSI SYNTAX │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ SELECT │ SELECT │ │ emp.deptno │ ename, │ │ FROM │ dname, │ │ emp, │ emp.deptno, │ │ dept │ dept.deptno │ │ WHERE │ FROM │ │ emp.deptno = dept.deptno(+); │ scott.emp LEFT OUTER JOIN scott.dept │ │ │ ON emp.deptno = dept.deptno; │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ RIGHT OUTER JOIN - CONVENTIONAL │ RIGHT OUTER JOIN - ANSI SYNTAX │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ SELECT │ SELECT │ │ emp.deptno │ ename, │ │ FROM │ dname, │ │ emp, │ emp.deptno, │ │ dept │ dept.deptno │ │ WHERE │ FROM │ │ emp.deptno(+) = dept.deptno; │ scott.emp RIGHT OUTER JOIN scott.dept │ │ │ ON emp.deptno = dept.deptno; │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ FULL OUTER JOIN - CONVENTIONAL │ FULL OUTER JOIN - ANSI SYNTAX │ ├───────────────────────────────────┼─────────────────────────────────────────────┤ │ SELECT │ SELECT │ │ * │ * │ │ FROM │ FROM │ │ emp, │ scott.emp FULL OUTER JOIN scott.dept │ │ dept │ ON emp.deptno = dept.deptno; │ │ WHERE │ │ │ emp.deptno = dept.deptno(+) │ │ │ UNION ALL │ │ │ SELECT │ │ │ * │ │ │ FROM │ │ │ emp, │ │ │ dept │ │ │ WHERE │ │ │ emp.deptno(+) = dept.deptno │ │ │ AND emp.deptno IS NULL; │ │ └───────────────────────────────────┴─────────────────────────────────────────────┘ 

    PS : leggi il riepilogo delle risposte per tutti gli aggiornamenti raggruppati.

    Se i tuoi oltre 200 pacchetti funzionano come previsto con la syntax “vecchio stile”, lascia che sia. SQL non inizierà a funzionare meglio dopo la migrazione alla syntax ANSI – è solo una syntax diversa.

    Detto questo, la syntax ANSI è più pulita: non si arriverà a un join normale se si dimentica (+) in un join esterno a più colonne.
    In passato c’erano alcuni bug con la syntax ANSI ma se si va con l’ultima versione 11.2 o 12.1 dovrebbe essere già risolta.
    Naturalmente, conoscete meglio il vostro ambiente e le vostre priorità – come ha detto SchmitzIT – La syntax ANSI fa parte dello standard SQL e sarebbe di aiuto quando si andrebbe ad utilizzare un altro prodotto RDBMS.

    In 11g dovresti utilizzare la syntax di join ANSI. È più flessibile (supporto per join esterni completi e join partizionati), e come afferma la documentazione:

    Oracle consiglia vivamente di utilizzare la syntax di join della clausola FROM più flessibile mostrata nell’esempio precedente.

    Questa è una ragione sufficiente.

    Raggruppando le risposte insieme

    1. Utilizzare JOIN espliciti piuttosto che impliciti (indipendentemente dal fatto che siano join esterni o meno) è che è molto più facile creare accidentalmente un prodotto cartesiano con i join impliciti. Con JOIN espliciti non puoi “per caso” crearne uno. Più sono coinvolte le tabelle, maggiore è il rischio di perdere una condizione di join.
    2. Fondamentalmente (+) è severamente limitato rispetto ai join ANSI. Inoltre è disponibile solo in Oracle, mentre la syntax di join ANSI è supportata da tutti i principali DBMS
    3. SQL non inizierà a funzionare meglio dopo la migrazione alla syntax ANSI – è solo una syntax diversa.
    4. Oracle consiglia vivamente di utilizzare la syntax di join della clausola FROM più flessibile mostrata nell’esempio precedente. In passato c’erano alcuni bug con la syntax ANSI ma se si va con l’ultima versione 11.2 o 12.1 dovrebbe essere già risolta.
    5. L’utilizzo degli operatori JOIN garantisce che il codice SQL sia conforms ANSI e consentirebbe quindi a un’applicazione front-end di essere portata più facilmente su altre piattaforms di database.
    6. Le condizioni di unione hanno una selettività molto bassa su ciascun tavolo e un’elevata selettività sulle tuple nel prodotto trasversale teorico. Le condizioni nell’istruzione where solitamente hanno una selettività molto più alta.
    7. Oracle converte internamente la syntax ANSI nella syntax (+), è ansible vedere ciò accade nella sezione Informazioni Predicato del piano di esecuzione.

    Possibile trappola nell’uso della syntax ANSI sul motore 12c

    Inclusa una possibilità di bug in JOIN in 12c. Vedi qui

    AZIONE SUPPLEMENTARE:

    Quest SQL optimizer tool riscrive la syntax SQL in ANSI.

    Oltre ai motivi menzionati da altri, l’utilizzo degli operatori JOIN garantisce che il codice SQL sia conforms ANSI e consentirebbe quindi a un’applicazione front-end di essere più facilmente trasferita per altre piattaforms di database.

    Separare i predicati in base alla selettività

    Separare la query in condizioni di join e in cui le condizioni possono fornire all’ottimizzatore un suggerimento aggiuntivo. Le condizioni di unione hanno una selettività molto bassa su ciascun tavolo e un’elevata selettività sulle tuple nel prodotto trasversale teorico. Le condizioni nell’istruzione where solitamente hanno una selettività molto più alta.

    In una condizione di join per ogni riga a sinistra è molto probabile un valore a destra (e viceversa). Quindi tali condizioni sono buone per unire i risultati di due tabelle, ma non aiutano molto ad eliminare i valori di ogni singola tabella dal set di risultati.

    Le condizioni nella clausola where in genere possono essere utilizzate per eliminare singole righe da una tabella dal set di risultati.

    Suggerimento per l’ottimizzatore (umano!)

    Quindi è una buona strategia per eseguire prima le condizioni sulle singole tabelle ed eliminare il maggior numero ansible di righe dal set di risultati. Successivamente, è ansible utilizzare le condizioni di unione per combinare le righe rimanenti.

    Non è chiaro se l’ottimizzatore Oracle utilizzi realmente la posizione della condizione nell’istruzione SQL come suggerimento per l’ottimizzazione della query. Immagino che sia più interessato ai fatti concreti nelle statistiche della tabella (ci sono stati alcuni cambiamenti nel modo in cui Oracle gestisce i diversi join in 11g R1, vedi questo post dal team di Oracle Optimizer per maggiori dettagli).

    Almeno per me, come umano, è molto utile sapere se una dichiarazione ha una selettività su un tavolo singe quando cerco di capire e ottimizzare una query. Dovresti considerare questo anche quando vuoi mettere più condizioni in una clausola ON (ad es. ON (ax=bx AND ay=by ) vs. ponendo una delle condizioni nel dove clasue: Basta controllare, quanto è selettiva la condizione.

    Conclusione

    Per le query esistenti mantenere la syntax così com’è. Quando crei una nuova query o rifattori uno esistente, prova a ordinare i predicati sulla selettività usando la syntax “JOIN ON”: Se non è selezionabile su una singola tabella, inseriscilo nella parte ON, altrimenti nella parte WHERE.

    Il segno (+) utilizzato in outer join è la syntax Oracle per join esterni

    Dalle informazioni raccolte da fonti oracle affidabili ho potuto vedere che è ansible mantenere la syntax Oracle outer join (+) per i pacchetti esistenti poiché ci sono più di 200 pacchetti e poiché internamente Oracle li converte ancora dalla syntax ANSI alla syntax Oracle.

    Si prega di utilizzare la syntax ANSI in futuro dove ci sono limitazioni per l’utilizzo dell’operatore (+)

    Si prega di trovare i collegamenti per una spiegazione dettagliata sul (+) segno Outer join che potrebbe aiutarti a decidere sulla tua migrazione

    Oracle Outer Join syntax e syntax ANSI

    Limitazioni dell’uso (+) Join esterni

    Ulteriori informazioni su Oracle outer join

    (+) Join esterno Operatore consigliato in Java quando si utilizzano i driver JDBC Oracle

    Come pratica, dovresti sempre usare la syntax ANSI. Meglio non rielaborare su pacchetti e procedure. Piuttosto puoi correggere le cose quando fai qualsiasi manutenzione su quegli script individualmente. Non ci sarà alcuna differenza nei piani a causa della syntax.

    Lo strumento di ottimizzazione SQL Quest riscrive con tutte le possibili combinazioni per trovare un piano migliore. Quindi è ancora necessario cercare uno SQL dai suoi 100+ risultati.

    Ho usato entrambi gli approcci su diversi progetti e preferisco la syntax JOIN .

    • C’è una chiara separazione per le condizioni di join nella clausola ON e nelle condizioni del filtro nella clausola WHERE .
    • È più facile leggere e conservare query di grandi dimensioni con molti join.

    Alcuni esperti hanno detto che la syntax (+) non consente i join esterni completi. Lo fa, quindi questo non è il problema: (LEFT OUTER JOIN) UNION ALL (RIGHT OUTER JOIN).

    Altri hanno detto che le prestazioni sono la ragione per fare il passaggio. Questo è un mucchio di BS, specialmente in SQL. Certo, ci sono alcune linee guida, ma ogni query e ogni database ha le sue peculiarità, è necessario sintonizzarsi su specifiche non per situazioni generali.

    I motivi per passare da (+), oltre a non essere standard, sono i suoi limiti rispetto alla nuova syntax esplicita: http://docs.oracle.com/cd/E16655_01/server.121/e17209/queries006.htm#SQLRF52354 . Iniziare a leggere da qui: “Oracle consiglia di utilizzare la syntax OUTER JOIN della clausola FROM anziché l’operatore Oracle join”.

    Parlando dall’esperienza lavorativa, l’uso del JOIN piuttosto che (+) è più semplice, più veloce, più bello e meglio lavorare con la soluzione, specialmente quando si lavora con selezioni multi database (attraverso sinonimi), con un sacco di tabelle ( es .: 40+ tavoli) in un grande database (più di 1000 tavoli, alcune tabelle con più di 2 miliardi di file), sentirai una grande differenza.