2009-12-17 4 views
9

Ho una vista che utilizza 11 outer join e due inner join per creare i dati. Ciò si traduce in oltre 8 milioni di righe. Quando eseguo il conteggio (*) sul tavolo, sono necessari circa 5 minuti. Sono in perdita su come migliorare le prestazioni di questo tavolo. Qualcuno ha qualche suggerimento su dove cominciare? Sembrano essere indici su tutte le colonne che si uniscono (anche se alcuni sono compositi, non sono sicuro se questo fa la differenza ...)Miglioramento delle prestazioni in una vista con un sacco di join

Qualsiasi aiuto apprezzato.

+1

hai esaminato i piani di esecuzione stimati/effettivi? ti diranno se ti manca un indice da qualche parte – dan

+1

l'ho guardato. Non ci sono scansioni di tabelle che occupano un momento significativo. Ci sono molte "partite di hash" che si sommano a scarse prestazioni, ma le partite di hash vengono eseguite solo quando gli indici sono usati corretti? –

+0

un trucco che ho trovato molto utile è quello di rompere una query complessa in subquery, ad es. se hai una query con 11 join in esso - è un duro lavoro per l'ottimizzatore che generalmente non è in grado di considerare più di 4 join contemporaneamente. Vorrei provare a mantenere la query esterna con 4 join per spostare altri join su sottoquery. Mi ha aiutato in alcuni casi – root

risposta

4

Questo è un problema complesso, con una visione complessa si hanno anche potenziali interazioni con le query sulla vista, garantendo così prestazioni ragionevoli sarà abbastanza difficile. Anche le viste esterne (in particolare quelle complesse) possono causare problemi a Query Optimiser.

Un'opzione sarebbe quella di materializzare la vista (denominata "viste indicizzate" su SQL Server). Tuttavia potrebbe essere necessario monitorare le prestazioni degli aggiornamenti per verificare che non imponga un sovraccarico eccessivo. Inoltre, i join esterni in una vista materializzata possono precludere l'aggiornamento in tempo reale; se è necessario, potrebbe essere necessario implementare nuovamente la vista come tabella denormalizzata e mantenere i dati con i trigger.

Un'altra possibilità sarebbe quella di esaminare se la vista potrebbe essere divisa in due o tre viste più semplici, possibilmente materializzando alcune ma non tutte le viste. Potrebbe essere più facile materializzare parte della vista e ottenere prestazioni dal sistema in questo modo.

+1

Avevo pensato di creare una vista indicizzata, ma da quello che ho capito non puoi farlo su una vista che usa qualsiasi tipo di join esterno. Mi sbaglio su questo? –

+0

Questo è corretto. Potresti essere in grado di materializzare parte della vista e poi costruire una vista sopra quella. In alternativa potresti essere in grado di ri-implementare la vista come una tabella gestita da una serie di trigger. – ConcernedOfTunbridgeWells

+0

Sì, penso che questo sia l'approccio che dovrò prendere. –

1

Un paio di cose che si potrebbe prendere in considerazione:

  1. denormalizzazione. Ridurre il numero di join richiesti denormalizzando la struttura dati
  2. partizionamento. Puoi partizionare i dati da tabelle grandi? per esempio. una tabella grande, potrebbe funzionare meglio se partizionata in un numero di tavoli più piccoli. Enterprise Edition da SQL 2005 in poi ha un buon supporto per il partizionamento, vedere here. Considera questo se si inizia a entrare nei reami di 10s/100s di milioni di righe
  3. gestione degli indici/statistiche. Tutti gli indici sono deframmentati? Le statistiche sono aggiornate?
1

Eseguire la procedura guidata sql profiler/index tuning. a volte fornisce raccomandazioni sugli indici che non hanno immediatamente senso, ma si rivelano ottimi vantaggi perf.

+0

Non sapevo che i consigli fatti da Profiler. Vuoi dire Query Analyzer? –

+0

scusa, lo strumento che effettivamente fa le raccomandazioni è "Ottimizzazione guidata dell'indice Sql Server". Questo strumento prende come input un file di traccia del profiler :-) –

2

la premessa di base è errata. avere una vista che restituisce 8 milioni di righe non è una buona idea perché realisticamente non si può davvero fare nulla con così tanti dati. 5 minuti suona bene per 8 milioni di conteggi() a causa di tutti quei join.

quello che devi fare è pensare al tuo problema aziendale e scrivere una query/vista più piccola.

0

Forse alcune delle tabelle che stai cercando di (outer) join sono disgiunte?Se è così, prendere in considerazione la creazione di stored procedure invece di vista e di creare qualcosa di simile:

select ... into #set1 from T1 left join T2 left join... where ...

select ... into #set2 from T3 left join T4 left join... where ...

...

select ... from #set1 left join #set2 left join ...

Con questo, si può evitare di elaborare enormi quantità di dati. Quando si creano join esterni, spesso l'ottimizzatore non può spostare la selezione nell'albero di analisi della query (se così fosse, non si otterrebbero righe con valori null che probabilmente si desidera)

Naturalmente non è possibile creare query con l'unione con stored procedure. Questa è solo un'idea di base che puoi usare.