Outer Apply vs Left Join Performance


37

Sto usando SQL SERVER 2008 R2

Mi sono appena imbattuto in APPLY in SQL e mi è piaciuto come risolve i problemi di query in così tanti casi,

Molti dei tavoli che stavo usando 2 join sinistro per ottenere il risultato, sono stato in grado di ottenere 1 applicazione esterna.

Ho una piccola quantità di dati nelle mie tabelle DB locali e dopo l'implementazione il codice dovrebbe essere eseguito su dati almeno 20 volte più grandi.

Temo che l'applicazione esterna potrebbe richiedere più tempo rispetto alle 2 condizioni di join a sinistra per una grande quantità di dati,

Qualcuno può dire come funziona esattamente l'applicazione e come influenzerà le prestazioni in dati molto grandi, se possibile alcune relazioni proporzionali con le dimensioni di ogni tabella come proporzionale a n1 ^ 1 o n1 ^ 2 ... dove n1 è il numero di righe nella tabella 1.

Ecco la query con 2 join a sinistra

select EC.*,DPD.* from Table1 eC left join
  (
   select member_id,parent_gid,child_gid,LOB,group_gid,MAX(table2_sid) mdsid from Table2
   group by member_id,parent_gid,child_gid,LOB,group_gid

  ) DPD2 on DPD2.parent_gid = Ec.parent_gid
        AND DPD2.child_gid = EC.child_gid
        AND DPD2.member_id = EC.member_id
        AND DPD2.LOB = EC.default_lob
        AND DPD2.group_gid = EC.group_gid
  left join
  Table2 dpd on dpd.parent_gid = dpd2.parent_gid 
            and dpd.child_gid = dpd2.child_gid
            and dpd.member_id = dpd2.member_id 
            and dpd.group_gid = dpd2.group_gid 
            and dpd.LOB = dpd2.LOB
            and dpd.table2_sid = dpd2.mdsid

Ecco la query con applicazione esterna

select * from Table1 ec   
OUTER APPLY (
      select top 1 grace_begin_date,retroactive_begin_date,Isretroactive
                    from Table2 DPD 
                    where DPD.parent_gid = Ec.parent_gid
                    AND DPD.child_gid = EC.child_gid
                    AND DPD.member_id = EC.member_id
                    AND DPD.LOB = EC.default_lob
                    AND DPD.group_gid = EC.group_gid
                    order by DPD.table2_sid desc
     ) DPD 

Risposte:


44

Qualcuno può dire come funziona esattamente applicare e come influenzerà le prestazioni in dati molto grandi

APPLYè un join correlato (chiamato a LATERAL JOINin alcuni prodotti e versioni più recenti dello standard SQL). Come ogni costruzione logica, non ha alcun impatto diretto sulle prestazioni. In linea di principio, dovremmo essere in grado di scrivere una query utilizzando qualsiasi sintassi logicamente equivalente e l'ottimizzatore trasformerebbe il nostro input esattamente nello stesso piano di esecuzione fisico.

Naturalmente, ciò richiederebbe all'ottimizzatore di conoscere ogni possibile trasformazione e di avere il tempo di considerare ciascuna di esse. Questo processo potrebbe richiedere più tempo dell'era attuale dell'universo, quindi la maggior parte dei prodotti commerciali non adotta questo approccio. Pertanto, la sintassi della query può e spesso influisce sulle prestazioni finali, sebbene sia difficile fare affermazioni generali su quale sia il migliore e perché.

OUTER APPLY ( SELECT TOP ... )È molto probabile che la forma specifica di comporti l'unione di cicli nidificati correlati nelle versioni correnti di SQL Server, poiché l'ottimizzatore non contiene la logica per trasformare questo modello in un equivalente JOIN. L'unione di loop nidificati correlati potrebbe non funzionare correttamente se l'input esterno è di grandi dimensioni e l'input interno non è indicizzato o le pagine necessarie non sono già in memoria. Inoltre, elementi specifici del modello di costo dell'ottimizzatore indicano che un'unione di cicli nidificati correlati ha meno probabilità di un semanticamente identico JOINper produrre un piano di esecuzione parallelo.

Sono stato in grado di fare la stessa query con un singolo join sinistro e row_number ()

Questo può o meno essere migliore nel caso generale. Sarà necessario testare le prestazioni di entrambe le alternative con dati rappresentativi. Il LEFT JOINe ROW_NUMBERcertamente ha il potenziale per essere più efficiente, ma dipende dalla precisa forma del piano di query scelta. I fattori primari che influenzano l'efficienza di questo approccio sono la disponibilità di un indice per coprire le colonne necessarie e per fornire l'ordine richiesto dalle clausole PARTITION BYe ORDER BY. Un secondo fattore è la dimensione della tabella. Un efficiente e ben indicizzato APPLYpuò superare un ROW_NUMBERindice ottimale se la query tocca una porzione relativamente piccola della tabella interessata. Sono necessari dei test.


2

La prima query può essere eseguita in parallelo da una sola richiesta al server sql. Ha recuperato tutto il record e fornisce output in base a criteri di filtro.

Ma nel caso del secondo viene eseguito riga per riga e per ogni riga verrà esaminata la Tabella2 e aggiunta il risultato.

se la tua query esterna ha meno record, la seconda è migliore (OUTER APPLY). Ma se la prima query può ottenere più dati, allora dovresti usare la prima.

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.