Come migliorare le prestazioni delle query vergini in MS SQL Server?


10

Ho un sito Web ASP.NET che esegue la propria memorizzazione nella cache indipendente di dati e che i dati non cambiano per lunghi periodi di tempo, quindi non è necessario interrogare SQL Server una seconda volta con la stessa query. Devo migliorare le prestazioni delle prime query (vergini) che vanno a quel SQL Server. Alcune query elaborano così tanti dati che potrebbero causare l'utilizzo di SQL Server tempdb. Non utilizzo variabili della tabella temporanea o tabelle temporanee, quindi SQL Server decide di utilizzare tempdbda solo ogni volta che è necessario.

La mia dimensione di db è di 16 GB, ho 32 GB di RAM fisica disponibile sul mio server.

Comprendo che la strategia di memorizzazione nella cache di MS SQL Server tenta di mantenere i dati nella RAM per accelerare le prestazioni di query simili se necessitano di caricare nuovamente gli stessi dati. Inoltre, proverà a utilizzare la RAM disponibile anziché tempdb per accelerare le prestazioni senza causare l'accesso al disco.

Suppongo che quando arriva la query che deve archiviare qualcosa in tempdb SQL Server e non c'è abbastanza RAM disponibile, SQL Server ha 2 opzioni:

1) per scaricare alcuni dati memorizzati nella cache e utilizzare la RAM risparmiata anziché tempdb per evitare scritture su disco

2) conservare i dati memorizzati nella cache per query future e iniziare a utilizzare tempdb, che rallenta le scritture.

Non so quale scelta farà SQL Server in questa situazione, ma vorrei che diventasse la scelta n. 1 perché mi preoccupo solo delle prestazioni delle query per la prima volta (vergine), perché non invio mai più la stessa query a SQL Server (anche se posso inviare una domanda simile).

Qual è la strategia di memorizzazione nella cache di SQL Server per questo scenario?

In che modo bilancia l'utilizzo della RAM tra evitare tempdb per le query vergini e la velocità delle query seconde?

È possibile configurare SQL Server in modo tale da fare la scelta n. 1? Se sì allora come?

In quale altro modo è possibile migliorare le prestazioni di tutte le query vergini SQL?

Poiché non conosco la strategia di memorizzazione nella cache di SQL Server, voglio posizionare il database sul disco RAM. Ciò assicurerà che qualsiasi query vergine abbia un'alta velocità di caricamento dei dati non memorizzati anche se SQL Server fa sempre la scelta n. 1. Il rischio è che SQL Server possa iniziare a utilizzare più tempdb con meno RAM disponibile (solo 16 GB rimanenti dopo aver usato 16 GB per il disco RAM) se continua a fare la scelta n. 2, che rallenterà le query vergini che causano lo spargimento tempdb.

Sono interessato alla soluzione per SQL 2008 R2, ma immagino che sia probabilmente la stessa per SQL 2008, SQL 2005 e potrebbe essere SQL 2000.

chiarimenti:

Non ci sono altre applicazioni in esecuzione su quella casella, è dedicata a SQL Server . Il sito Web funziona su una scatola separata.

È SQL Server 2008 R2 Standard Edition 64 bit su Windows Server 2008 R2 Enterprise 64 bit.

Eseguo solo query di sola lettura e il database è impostato per essere di sola lettura .

Supponiamo che ci siano già buoni indici . Questa domanda riguarda SQL Server che fa la scelta n. 1 contro la scelta n. 2, come lo fa, se esiste un modo per controllarlo e se il disco RAM lo aiuta a fare la scelta giusta per le query vergini.


Cosa ti fa pensare che tempdb sia utilizzato anche se non stai creando tabelle temporanee? Stai utilizzando tabelle distinte o raggruppate per tabella?
darin strait

3
32/64 bit? Fisico o virtuale? Questo server è dedicato a SQL Server o stai eseguendo anche IIS o altre app nella stessa casella? Hai fatto qualche analisi del piano di esecuzione della query? Puoi pubblicare domande di esempio e / o piani di esecuzione? E ancora uno per fortuna ... segui la guida di Kendra per la registrazione di sp_whoisactive mentre la tua domanda del problema è in esecuzione e pubblica l'output.
Mark Storey-Smith,

@darinstrait La spiegazione più probabile sarebbe una sorta di fuoriuscita di hash.
Mark Storey-Smith,

Risposte:


7

La tua domanda può essere sostanzialmente riformulata come "Come funziona la concessione della memoria della query?". Una buona lettura sull'argomento è capire la concessione della memoria del server SQL . Prima che una query venga avviata, potrebbe essere necessaria una concessione di memoria per ordinamenti, hash e altre operazioni che richiedono molta memoria. Questa concessione di memoria è una stima . In base allo stato corrente del sistema (numero di richieste in esecuzione e in sospeso, memoria disponibile ecc.) Il sistema concede alla query una concessione di memoria fino alla quantità richiesta. Una volta concessa la memoria, la query avvia l'esecuzione (potrebbe essere necessario attendere nella temuta coda "semaforo delle risorse" prima di ottenere la concessione). All'esecuzione è garantita la concessione di memoriadal sistema. Questa quantità di memoria può essere condivisa con le pagine di dati (poiché possono sempre scaricarsi su disco) ma mai con altri utilizzi di memoria (cioè non può essere soggetta a "furto"). Pertanto, quando la query inizia a richiedere memoria impegnata dalla propria concessione, il motore distribuirà quella che si chiama "strategia n. 1": le pagine di dati possono essere sfrattate (svuotate se sporche) al fine di dare alla query la memoria promessa. Ora se la stima era corretta e la concessione era pari al 100% della memoria richiesta, la query non dovrebbe "riversarsi". Ma se la stima non era corretta (si riduce a stime di cardinalità, quindi è soggetta a statistiche non aggiornate) o se la query non ha ottenuto l'intera sovvenzione richiesta, la query "si spargerà". Questo è quando tempdb entra in scena e le prestazioni di solito i carri armati.

L'unica manopola che hai a disposizione per controllare qualcosa in questo processo è il Resource Governor . Poiché RG può essere utilizzato per specificare un'impostazione MIN per un pool, può essere utilizzato per riservare memoria per un determinato carico di lavoro in modo che ottenga effettivamente la concessione di memoria richiesta. Ovviamente, dopo aver effettuato le opportune indagini che dimostrano che le riduzioni di memoria sono il colpevole, e ovviamente dopo che è stato valutato l'impatto su altri carichi di lavoro. E testato, ovviamente.

Ora torniamo alla domanda originale. Se la tua indagine è corretta (un grandissimo if) vorrei sottolineare due problemi:

  • si esegue query di produzione che richiedono assegnazioni di memoria per un sito Web . Questo è un grande no-no. Le assegnazioni di memoria sono indicative di query analitiche che non hanno spazio per soddisfare le richieste HTTP.
  • le tue query non sono probabilmente eventi che ottengono la concessione di memoria richiesta. Ancora una volta, ancora di più un no-no per un carico di lavoro critico per la latenza come lo sono i siti web.

Quindi quello che mi dice è che hai un problema progettuale e architettonico fondamentale. I siti Web sono guidati dalla latenza e dovrebbero creare un carico di lavoro come OLTP, senza assegnazioni di memoria e senza pressione sulla memoria per le query. Per non parlare di sversamenti. Le query analitiche devono essere eseguite in processi offline e archiviare i risultati preelaborati per una rapida disponibilità quando le richieste HTTP li desiderano.


@Mark: la maggior parte delle query non richiede alcuna concessione di memoria. Solo pochi operatori (in particolare l'ordinamento e l'hash join) hanno bisogno di un buffer di lavoro e quindi richiedono una sovvenzione. Questa è la "nomenclatura" standard. Potresti pensare all'ambiente di esecuzione e al piano di esecuzione della query, di cui ogni singola query richiede uno e include un po 'di memoria. Una concessione di memoria è molto più grande (MB). In secondo luogo, guarda sys.dm_exec_query_memory_grants: hai requested(il massimo), required(il minimo) e granted(il reale).
Remus Rusanu,

Scuse. Avevo rilevato da qualche parte che il minimo per query era assegnato dallo stesso impiegato della memoria, il che era errato.
Mark Storey-Smith,

Non sono ancora sicuro di essere d'accordo con i tuoi due punti elenco. Qualsiasi tipo di operazioni banali e operazioni di hash join richiedono sovvenzioni al livello minimo, quindi suggerire che debbano essere eliminate del tutto sembra eccessivo. Che sversamenti a tempdb da sovvenzioni insufficienti siano una bandiera rossa è certamente ragionevole ma un divieto generale su qualsiasi operazione che richiede una sovvenzione potrebbe mettere molte persone su un inutile percorso di ottimizzazione preventiva?
Mark Storey-Smith,

OP afferma di avere tutti gli indici necessari. Se questo è vero e il carico di lavoro ha abbastanza problemi di concessione della memoria (e persino di fuoriuscita) da essere evidente, allora direi che il carico di lavoro è troppo analitico per un sito web . In definitiva, l'ottimizzazione delle prestazioni è sempre un gioco di indagine per determinare la causa principale. Tutte le dichiarazioni e i divieti generali trovano sempre un contro esempio che li dimostra errati, questo è un dato di fatto. L'OP ha un problema di progettazione che crea un carico di lavoro troppo analitico? Non lo so. Penso che lo faccia? Direi l'87,5% di fiducia sì.
Remus Rusanu,

@Remus: la tua ipotesi è stata buona, le mie domande sul sito web sono analitiche al 100%. Consente agli utenti di costruire qualsiasi possibile query nell'interfaccia utente per inviare qualsiasi possibile combinazione di filtri, aggregati e raggruppamenti a SQL Server (che, ovviamente, rende difficile l'indicizzazione). Sì, potrei farli funzionare in modalità asincrona salvando i risultati per un successivo recupero, ma l'obiettivo è quello di fare in modo che qualsiasi query venga eseguita così velocemente che il risultato sia immediatamente disponibile dopo 2-10 secondi e anche la query analitica è l'unica funzione di quel sito Web , Penso che renderli asincroni abbia senso solo se ci sono altre query che non sono analitiche.
alpav,

3

Ciò che non hai menzionato è il tipo di query eseguite sul database e se esistono indici corretti per accelerare le prestazioni delle query.

È inoltre necessario assicurarsi che ci siano altre applicazioni in esecuzione nella stessa casella. Anche se la scatola ha 32 GB di RAM, hai impostato qualsiasi impostazione di memoria massima sul server di database per porre un limite artificiale. Se ci sono app in esecuzione sullo stesso server, SQL e le altre app potrebbero competere per le risorse e notare che SQL ha molta fame di memoria.

SQL Server utilizzerà tempdb per l'ordinamento interno o hash join / aggregati o operatori di spool ecc. E non è possibile controllare questo comportamento. Quello che puoi fare è limitare la quantità di dati restituiti.

Hai controllato le statistiche di attesa in questa casella? Ogni volta che SQL Server è in attesa di una risorsa, SQL Server monitorerà la risorsa di attesa e la ricerca di tali informazioni aiuta.

Guarda le domande diagnostiche di Glenn Berry e sarà un buon inizio per te.

Guarda anche PARAMETERIZATION FORCED come menzionato in http://weblogs.sqlteam.com/dang/archive/2009/06/27/Forced-Parameterization-A-Turbo-Button.aspx


ok, supponiamo che ci siano già indici giusti. Ho dimenticato di menzionare che si tratta di un database di sola lettura con query di sola lettura e non ci sono altre applicazioni in esecuzione sulla casella Server SQl.
alpav,

Le tue statistiche sono aggiornate? I database di sola lettura non possono creare statistiche se mancano o non sono aggiornati. I tuoi dati sono distorti o ha valori univoci per la chiave. Ci sono molti fattori che possono causare questo comportamento.
Sankar Reddy,

Cosa intendi con "questo comportamento"? Non ho detto che qualcosa non va. Voglio solo migliorare le prestazioni in circostanze speciali. SQL Server è ottimizzato per l'esecuzione in qualsiasi situazione, ma può o non può funzionare nel modo migliore nella mia situazione. Non sono sicuro di potermi fidare di SQL Server per fare una scelta equilibrata n. 1 contro n. 2. Ogni volta che inserisco nuovi dati, eseguo sp_updatestats.
alpav,


2
Quando si esegue sp_updatestats, qual è il rapporto di esempio scelto. Il rapporto predefinito è molto campione e dipende dalla dimensione dell'indice. Se le query richiedono principalmente (solo) i nuovi dati e anche se si eseguono sp_updatestats, SQL Server non può prendere decisioni divine sui piani di esecuzione.
Sankar Reddy,

2

Questa domanda al momento si presenta come una soluzione alla ricerca di un problema. Hai deciso che la soluzione è un disco RAM e vuoi che qualcuno convalidi tale scelta. Spiacente, non succederà.

Se hai misurato e osservato una fuoriuscita in tempdb, sarà quasi sicuramente dovuto a un'operazione di ordinamento o hash e a una concessione insufficiente della memoria della query. A seconda del volume di dati da elaborare, ciò può essere inevitabile, ma buone probabilità che la query e / o l'indicizzazione possano essere migliorate per evitarlo.

Dai un'occhiata a Buffer Management per capire meglio come SQL Server gestisce la memoria e SQL Server Memory Management Spiegato per alcuni strumenti di base e query DMV per capire dove è allocata la tua memoria.

In quale altro modo è possibile migliorare le prestazioni di tutte le query vergini SQL?

Questo è un argomento importante. Pubblica la query e il piano e otterrai un feedback mirato.

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.