Suggerimenti per l'ottimizzazione delle query di SQL Server 2005/8


13

Sto cercando di educare un team a scrivere query SQL Server migliori e mi chiedevo quali fossero i migliori suggerimenti delle persone per migliorare le prestazioni.

Ad esempio, una volta ho avuto un DBA che ha insistito sul fatto che il conteggio (*) avrebbe avuto prestazioni peggiori del conteggio (1) (non ho idea se avesse ragione o se fosse ancora valida rispetto agli ultimi ottimizzatori di query).

Quali cose semplici dovrei dire al team di provare e usare o evitare sempre? Sono idealmente alla ricerca di cose che (a) potrebbero fare una differenza ragionevole e (b) siano dirette, 1 - 2 righe da dichiarare.

Risposte:


13

Ottimizzazione delle query 101

Non esiste un proiettile d'argento magico per interrogare l'ottimizzazione, anche se posso darti alcuni consigli e suggerimenti. La prima cosa da fare è capire cosa sta succedendo dietro le quinte. Ottieni un buon libro interno come il terzo libro della Guida del Guru.

Le query con prestazioni scarse tendono a presentarsi in due varianti di base: query transazionali che richiedono troppo tempo e lavori di rettifica batch (o report) che richiedono troppo tempo. Un buon segno di una query con qualcosa di sbagliato in esso è un singolo elemento nel piano di query che impiega il 99% delle volte.

Query transazionali

Nella maggior parte dei casi, una query transazionale con prestazioni scarse è una delle poche cose:

  • Un indice mancante. Puoi vederlo nel piano di query: scansioni di tabelle di tabelle di grandi dimensioni su un join che dovrebbero essere molto selettive (ovvero restituire poche righe).

  • Query impossibile utilizzare un indice. Se nella clausola where sono presenti condizioni OR, join su un valore calcolato o qualche altro elemento nella query che non è possibile eseguire ilarging, potrebbe essere necessario riscrivere la query. In breve, i sarg sono predicati di query che possono utilizzare gli indici per eliminare le righe. AND logico, uguaglianza e disuguaglianza (>,> =, <, <= e! =) Sono tutti identificabili. OR non è tradizionalmente compatibile. Tuttavia, è spesso possibile tradurre gli OR in predicati di cui è possibile eseguire il sarging invertendo il senso da OR a costrutti di tipo NOT (foo e not bar).

  • Predicati inefficienti. Ad esempio, se si ha un where inriferimento a una sottoquery nidificata, vedere se può essere riscritta come where existso come join. Ciò può comportare piani di query più efficienti e qui ci sono altre riscritture standard che puoi provare anche. Ancora una volta, le guide del Guru e altri sull'argomento sono un buon punto di partenza.

Query batch

Le query batch sono più complicate e presentano diversi problemi di ottimizzazione. Alcuni consigli sono:

  • Indicizzazione. Ciò può fare una grande differenza per lo stesso motivo delle query transazionali. Spesso un buon segno di un indice mancante è una lunga operazione di rettifica (99% del piano di query) che non sembra colpire la macchina.

  • Tabelle temporanee. Potrebbe essere meglio suddividere una query in più query popolando tabelle temporanee. Query più grandi danno all'ottimizzatore più spazio per rovinare, anche se questo è un problema minore rispetto al passato. Creare le tabelle temporanee con select intoquesta operazione che viene minimamente registrata (molto meno attività di registro), il che riduce il carico di I / O.

    Si noti che le tabelle temporanee in tempdb sono la stessa struttura di dati utilizzata dall'ottimizzatore per memorizzare i risultati dei join intermedi, quindi non vi è alcuna penalità di prestazione per questo. È inoltre possibile creare un indice (compresi gli indici cluster e di copertura) su una tabella temporanea, che può migliorare le prestazioni delle query leggendole per gli stessi motivi per cui migliorano le query su tabelle statiche.

    Non esagerare con le tabelle temporanee, poiché possono rendere le cose più difficili da rintracciare attraverso la query. Per tabelle più piccole all'interno di una stored procedure, verificare se le variabili di tabella sono utili. Si tratta di una struttura di dati in memoria, quindi possono essere una vittoria delle prestazioni.

  • Indici raggruppati e di copertura. Questi possono migliorare le prestazioni di una query in quanto forzano la località di riferimento sul disco in base a una colonna di raggruppamento. Un indice cluster può fare una grande differenza nelle prestazioni di un processo batch.

  • Predicati inefficienti. Questi possono causare problemi con sargs e altri problemi di subottimizzazione più o meno allo stesso modo delle query transazionali.

  • La scansione della tabella è tua amica. Contrariamente alla credenza popolare, le scansioni da tavolo non sono intrinsecamente malvagie. Generalmente sono un segno di qualcosa di sbagliato in una query transazionale, ma sono spesso il modo più efficiente per eseguire un'operazione batch di grandi dimensioni. Se stai facendo qualcosa con più di qualche percento di righe in una tabella, una scansione della tabella è spesso il modo più efficiente per coprire la tabella.

  • Unisci anelli annidati. Dai un'occhiata a cosa sta facendo l'ottimizzatore su entrambi i lati del join. Questi possono essere inefficienti se lo si sta eseguendo (ad esempio una tabella che esegue la scansione di due tabelle di grandi dimensioni su entrambi i lati di un'unione di cicli nidificati. Prendere in considerazione l'uso di indici cluster o order byprovare a modificare l'operazione in un'unione di unione o un suggerimento per promuovere un'unione di hash se una parte è abbastanza piccolo per farlo.

Locking

Il blocco può anche causare problemi di prestazioni. Se il tuo sistema funziona male sotto carico, guarda i contatori di profiler e perfmon relativi ai blocchi e controlla se c'è qualche contesa significativa. sp_who2ha una colonna 'BlkBy' nel set di risultati che mostrerà se una query è bloccata e cosa la sta bloccando. Inoltre, i profili con eventi 'deadlock graph' (se si hanno query deadlocking) ed eventi relativi al blocco possono essere utili per risolvere i problemi di blocco.


1
+1 dato che si tratta di ottime informazioni sull'ottimizzazione delle prestazioni (ho avuto il piacere di frequentare le lezioni di Kalen. Sa di cosa si occupa!). Potresti semplicemente aggiungere alcune informazioni sulle viste dinamiche.
Wayne,

3

Suggerimento migliore: utilizzare SQL Server 2008 ed eseguire Activity Monitor mentre i test sono in esecuzione. Nota le query che impiegano più tempo / hanno il maggior numero di I / O, ecc. Fai clic con il pulsante destro del mouse su quelle query per visualizzare la query e / o il piano di esecuzione.

Avanti: impara a capire i piani di esecuzione.

Successivo: utilizzare la procedura guidata di ottimizzazione del database.

Questi passaggi ti aiuteranno a generare i tuoi "migliori suggerimenti".



1

Innanzitutto, indicizzazione. Molte persone non si rendono conto che le chiavi esterne non ottengono automaticamente gli indici. Poiché sono utilizzati nei join, quasi sempre dovrebbero avere un indice.

Esamina attentamente tutti i cursori per vedere se possono essere sostituiti da un codice basato su set. In questo modo ho modificato il codice che funzionava da ore a secondi.

Evita le subquery. Se li hai nel codice sostituiscili con join o join in tabelle derivate.

Assicurati che la clausola where sia ampia.

Impara a leggere i piani di esecuzione.

Assicurati che l'ufficio abbia un paio di buoni libri sulla messa a punto delle prestazioni.

Le variabili di tabella sono migliori delle tabelle temporanee in alcuni casi e le tabelle temporanee funzionano meglio in altri, se è necessario utilizzarle, provare entrambe e vedere quale funziona meglio in quel caso particolare.

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.