2010-04-11 11 views
10

Ho una procedura memorizzata abbastanza complessa (o brutta a seconda di come la si guarda) in esecuzione su SQL Server 2008. Basa gran parte della logica su una vista che ha una tabella pk e una tabella fk. La tabella fk viene lasciata unita alla tabella pk leggermente più di 30 volte (la tabella fk ha un design scarso - utilizza coppie di valori nome che devo appiattire. Sfortunatamente, è di terze parti e non posso cambiarlo).La generazione del piano di query SQL richiede 5 minuti, la query viene eseguita in millisecondi. Che cosa succede?

In ogni caso, funzionava bene da settimane fino a quando non ho notato periodicamente una corsa che richiedeva 3-5 minuti. Si scopre che questo è il tempo necessario per generare il piano di query. Una volta che il piano di query esiste e viene memorizzato nella cache, la stored procedure stessa viene eseguita in modo molto efficiente. Le cose funzionano senza problemi finché non c'è un motivo per rigenerare e memorizzare nuovamente il piano di query nella cache.

Qualcuno ha visto questo? Perché ci vuole così tanto tempo per generare il piano? Ci sono modi per farlo venire con un piano più veloce?

risposta

3

Puoi provare a utilizzare Plan Guide. La generazione dei piani durerà ancora un po 'di tempo, ma dovrebbe essere significativamente più breve.

2

Hai considerato di riscrivere il tuo 30-join SELECT a smth come questo?

SELECT [key], NULL AS [a], NULL AS [b] 
    INTO #temp 
    FROM [pk-table] 

UPDATE t SET t.[a] = fk.[a], t.[b] = fk.[b] 
    FROM #temp t 
    INNER JOIN (
    SELECT f.[key], 
     MAX(CASE WHEN f.[name] = 'a' THEN f.[value] ELSE NULL END) AS [a], 
     MAX(CASE WHEN f.[name] = 'b' THEN f.[value] ELSE NULL END) AS [b] 
    FROM [fk-table] f 
    GROUP BY f.[key] 
    ) fk ON (fk.[key] = t.[key] 

Anche se non è forse una risposta alla tua domanda iniziale :)

+0

Anche questo vale la pena. Anche se ho provato PIVOT e alcuni CTE e finora la sinistra si unisce come una vista è stata la più efficiente. Hai visto in questo modo essere più veloce prima? – TheEmirOfGroofunkistan

+0

Sì. Ho avuto la stessa logica (più (circa 20) left-join di "fk-table" in una "master-table"), e il tempo di esecuzione è aumentato drasticamente dopo aver aggiunto un altro join della stessa tabella. Riscrivere l'aggiornamento "gigante" con selezione a due passaggi ha davvero aiutato. Ma forse era solo un caso particolare di indici sfortunati, non sono andato a scavare. (E scusa, mancata "su una vista" nel tuo post) –

+0

np - la vista semplifica il riutilizzo della query, non sono sicuro che sia necessario. – TheEmirOfGroofunkistan

2

qualcosa dovrà causato il piano per richiedere la ricompilazione, come un aggiornamento delle statistiche o il cambiamento DDL. L'elenco se qui: Execution Plan Caching and Reuse

La query nel suo modulo corrente richiederà sempre 3-5 minuti per ricompilare: questo non può essere evitato.

Supponendo che non sia possibile cambiarlo (PIVOT, utilizzare un trigger per mantenere una tabella "corretta" ecc.), Quindi è possibile controllare solo quando avviene la ricompilazione.

La risposta della guida di piano di Remus è a senso unico. Guarderei anche il mio mantenimento statistico e assicurerei che sia fatto dire durante la notte, quindi succede solo una volta all'inizio del giorno

+0

Grazie. Sto cercando di evitare di usare la guida del piano a meno che non sia davvero necessario. Forzare le statistiche durante la notte è una buona soluzione. Inoltre, avevamo pensato di provare a usare i trigger. Non abbiamo ancora una buona idea del carico effettivo sul tavolo poiché non è ancora un sistema live.Ma mi piacerebbe provarlo. – TheEmirOfGroofunkistan

Problemi correlati