C'è un modo per determinare se le query di SQL Server sono in esecuzione in memoria o sul disco?


13

Mi sono imbattuto in una serie di procedure memorizzate in un'applicazione oggi chiamate ripetutamente all'interno di un processo di lunga durata. All'interno di ciascuna procedura ho trovato più istruzioni select diverse, alcune all'interno di loop; non sorprende che queste routine attualmente in uso impieghino diversi minuti per l'esecuzione, quando l'intuizione si aspetterebbe che si completassero in pochi secondi.

Sembra abbastanza ovvio che le prestazioni non sono state prese in considerazione quando sono state scritte queste procedure, ci sono più casi di cose che non sono "una buona idea".

L'elaborazione di ogni riga durante l'importazione dei dati richiede 300 ms per riga, quindi le importazioni relativamente piccole richiedono diversi minuti per l'elaborazione.

Tuttavia, le tabelle coinvolte nelle procedure sono per lo più piuttosto piccole. Sto pensando, se tutte queste tabelle sono completamente residenti nella memoria, forse non c'è molto da guadagnare riscrivendo tutto questo.

Sto cercando di determinare .... per questo codice ovviamente inefficiente, che impatto reale sta avendo? Vale la pena aggiustarlo?

Quindi la domanda è:
- c'è un modo per determinare quali tabelle sono interamente bloccate in memoria?
- esiste un modo per attivare la traccia per monitorare le procedure memorizzate nidificate per trovare le parti particolarmente costose?

Nota: questo è su SQL Server 2008 R2

Risposte:


12

È possibile utilizzare una di queste due query per visualizzare le letture logiche totali e le letture fisiche totali.

SELECT  DB_NAME(st.dbid) Db,
        OBJECT_NAME(st.objectid, st.dbid) Prc,
        qs.execution_count,
        qs.total_logical_reads,
        qs.total_physical_reads,
        qs.statement_start_offset,
        qs.statement_end_offset,
        st.text
FROM    sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st;

SELECT  DB_NAME(database_id) Db,
        OBJECT_NAME(object_id, database_id) Prc,
        execution_count,
        total_logical_reads,
        total_physical_reads
FROM    sys.dm_exec_procedure_stats ps;

Il primo lo suddivide per istruzione, il secondo conta nell'intera procedura.

Le letture fisiche vengono lette sul disco, le letture logiche sono contro la memoria. Puoi usarlo per capire quali procedure o istruzioni sono le più costose nel tuo sistema e provare a mettere a punto quelle.

Tieni presente che, mentre le letture logiche sono significativamente più economiche delle letture fisiche, sono comunque costose, quindi ridurne il numero (ad esempio aggiungendo un indice appropriato) può rendere le tue query molto più veloci.

Ci sono molte colonne aggiuntive nei DMV sopra che potresti trovare interessanti.


In che modo un indice aiuta a ridurre le letture logiche?

In SQL Server tutti i dati sono organizzati in blocchi, di dimensioni 8 KB. Questi blocchi sono chiamati "pagine".

Ogni tabella contiene pagine "meta" che contengono informazioni sullo struktur della tabella e pagine pata. Se non esiste alcun indice ed esegui una query come SELECT * FROM tbl WHERE Id = 7SQL Server, devi cercare questa o queste righe nell'intera tabella. Quindi legge in una pagina alla volta, scorre attraverso tutte le righe di ciascuna pagina per determinare le righe che si adattano alla WHEREclausola. Pertanto, se la tabella richiede l'archiviazione di 1.000.000 di pagine, l'esecuzione di questa query richiederà 1.000.000 di letture logiche.

Se si dispone di un indice, SQL Server ordina i dati in modo logico all'interno delle pagine e stabilisce un elenco collegato tra le pagine. Ciò consente di eseguire query con un ORDER BYda eseguire senza un'operazione di ordinamento costosa. Ma soprattutto, l'ordinamento, SQL Server aggiunge un albero B + alla tabella. Un albero B + è una struttura paragonabile all'indice di un libro, in cui la ricerca di una parola chiave specifica mi consente di passare direttamente alla pagina che contiene la parola chiave. Il libro tipico ha solo un livello di indice mentre un albero B + può averne più. Basti pensare a un libro di grandi dimensioni, in cui l'indice stesso è lungo più pagine. In un caso del genere ha senso aggiungere un livello di indice aggiuntivo che ci dice su quale pagina si Strovano le parole di indice che iniziano con .

Gli alberi B + sono ottimizzati per avere il minor numero possibile di livelli, fornendo al contempo la proprietà di poter trovare qualsiasi record nell'indice leggendo una pagina per livello di indice. Quindi supponi la WHERE Id = 7query sopra quando hai un indice ordinato per Id. Diciamo che l'indice ha 5 livelli. Ora, per trovare tutti i record che corrispondono a questa query, devo leggere una pagina per livello di indice (ovvero 5 pagine). Questo si chiama "Ricerca indice". Se ci sono più record che si adattano al conto, potrei dover seguire l'indice ordinato per un po 'per recuperarli tutti. Ma supponiamo che ci sia un solo record.

Quindi, senza che l'indice in esecuzione quella query richiedesse 1.000.000 di letture, con indes sono necessarie 5 letture. Anche se una lettura logica è un'operazione in memoria, c'è un costo sostanziale - in realtà è l'operazione più costosa in una query banale come quella sopra. Quindi ridurre la quantità di letture logiche necessarie di un fattore di 200.000 accelererà la tua query di un fattore simile.

Pertanto, una lettura logica non equivale a una scansione di tabella, ma una scansione di tabella provoca molte più letture logiche di una ricerca di indice.


> "... la riduzione del numero di essi (ad esempio aggiungendo un indice appropriato) può rendere le tue query molto più veloci." Potresti spiegare come l'aggiunta di un indice ridurrà (?) Le letture logiche? La lettura logica è sinonimo di scansione di una tabella?

1
Aggiunta una spiegazione alla mia risposta sopra.
Sebastian Meine,

Grazie. Anche supponendo che gli indici corretti siano presenti su tutte le tabelle coinvolte ... Penso che ci sia ancora una grande differenza di prestazioni tra una tabella bloccata in memoria rispetto alla lettura dal disco (presupponendo gli stessi indici in entrambi gli scenari) ... o in altri parole, l'aggiunta di indici ti darà un aumento delle prestazioni% inferiore su un computer con molta RAM rispetto a un computer con meno memoria .... giusto?

1
l'accesso al disco fisico è chiaramente un ordine di grandezza più costoso dell'accesso alla memoria. Quindi prendere misure per evitarlo ti porterà molto lontano. Dovresti comunque esaminare prima il numero di letture logiche durante l'ottimizzazione delle query. Tenendoli bassi, a loro volta si mantengono basse le letture fisiche. Vi è anche un'alta probabilità che le pagine non debbano essere eliminate dalla cache riducendo ulteriormente le letture fisiche richieste.
Sebastian Meine,

2
Minore nitpick - Penso che le pagine siano 8kb :-). Buona risposta.
onupdatecascade

3
  • c'è un modo per attivare la traccia per monitorare le procedure memorizzate nidificate per trovare le parti particolarmente costose?

È possibile utilizzare SQL Profiler. Quando si avvia la traccia, è necessario scegliere RPC Completato, SP Avvio, SP StmtStarting e SP StmtCompleted (vedere l'immagine seguente)

inserisci qui la descrizione dell'immagine

Ciò consentirà di visualizzare tutte le query eseguite all'interno delle procedure memorizzate. Ti permetterà di vedere quante volte viene chiamata una procedura memorizzata nidificata. Al termine della traccia, è necessario salvarla. Quindi, riaprilo e, successivamente, sarai in grado di filtrare (con il pulsante "Filtri colonna") per trovare le query che ti causano problemi. (es: le query che hanno richiesto più di x letture o che sono durate più di x secondi (durata) ...)

Le opzioni del profiler che ti ho mostrato mostrano anche il piano di esecuzione, che è anche di grande aiuto.


1

Sembra una domanda generale di ottimizzazione delle query. Dalla tua descrizione vorrei:

  1. Guarda il codice per vedere se esegue l'elaborazione riga per riga. In tal caso, spesso è possibile effettuare ordini di miglioramento della grandezza implementando la stessa logica utilizzando set (più righe elaborate contemporaneamente). In altre parole, se si comporta come "loop su ogni riga", cambiarlo in "elabora tutte le righe". SQL eccelle per questo perché l'ottimizzatore può scegliere tra più metodi possibili, potenzialmente usare il parallelismo, rimuovere un sacco di overhead che proviene da una riga alla volta.
  2. Assicurati, poi, che ci siano indici che supportano il lavoro. Spesso, anche in questo caso, si possono ottenere ordini di miglioramento della grandezza con indici corretti rispetto a quelli non. Questo è vero in memoria e con accesso al disco. I processi possono comunque richiedere ore con tutto nella RAM se non ci sono indici appropriati su un set di dati di grandi dimensioni.
  3. Quindi, con la logica impostata e gli indici in atto, vorrei verificare se le pagine di dati interessate si adattano alla memoria. A questo punto, se c'è ancora molto accesso al disco, guardare le letture fisiche e l'attività del disco ha senso, perché tutti i grandi guadagni derivanti dall'ottimizzazione vengono effettuati nei primi due passaggi.
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.