Macchine identiche (?) SQL Server 2005; la query richiede 2 secondi su uno, 15 minuti sull'altro


12

L'ambiente:

Abbiamo due macchine Windows Server 2003 R2 a 32 bit che eseguono SQL Server 2005. Le configurazioni hardware sono server identici con CPU Xeon 5160, 4 GB di RAM e 13 GB di RAID0. I flag AWE e / 3GB non sono abilitati.

I server sono stati configurati parallelamente utilizzando un elenco di controllo di installazione predefinito e TUTTO il software installato è uguale su entrambi i computer.

Ogni impostazione di installazione del server SQL e livello di patch che sappiamo verificare sono identici. Una differenza è che TEMPDB è 400 MB sulla macchina veloce e 1,2 GB sulla macchina lenta. Tuttavia, in entrambi i casi, non vediamo alcuna allocazione TEMPDB in corso.

Il problema:

Esiste una procedura memorizzata che viene eseguita in 2 secondi su uno, ma 15 minuti sull'altro. Durante i 15 minuti aggiuntivi, l'attività del disco è scarsa o assente, non cambia l'utilizzo della memoria, ma un core della CPU è bloccato al 100% per tutto il tempo.

Questo comportamento persiste anche quando viene eseguito il backup dei database da uno e ripristinato all'altro.

Poiché si tratta di una procedura memorizzata, il monitor delle attività e il profiler non ci mostrano alcun dettaglio su dove si stia svolgendo questa attività della CPU nella procedura memorizzata.

La domanda:

Cos'altro dovremmo guardare?

Azione supplementare:

La lentezza si verifica nelle istruzioni FETCH NEXT per la seguente definizione del cursore:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE X NOT IN (SELECT X FROM dbo.B)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
...

Ciascuna delle istruzioni FETCH - su una tabella contenente solo circa 1000 righe - richiede circa 7,25 minuti. (No, non so perché fa due di fila, è necessario chiedere agli sviluppatori, ma funziona correttamente su entrambi i server).

Sono un po 'sospettoso di questo "NON IN (SELEZIONA ...)", poiché sembra che le letture virtuali siano davvero alte.


Come possono essere registrati i record in dbo.B e dbo.BX?
Mark Storey-Smith,

1
sono curioso di sapere se ci sarebbe una differenza di prestazioni se si fosse scelto questo: selezionare dbo.ax, dbo.ay da dbo.a sinistra join esterno dbo.b su dbo.ax = dbo.bx dove dbo.bx è null e z <= 0
DForck42

Un altro pensiero da aggiungere al mix. Sei sicuro che il rallentamento sia dovuto al recupero del cursore? Stai determinando questo dal piano di esecuzione (che riguarda tutto le stime) o da una traccia del profilo?
Mark Storey-Smith,

Viene da una traccia del profilo.
Ryandenki,

I piani di esecuzione sono gli stessi? È possibile che uno di loro stia utilizzando un piano di esecuzione errato.
Zane,

Risposte:


7

L'utilizzo di una metodologia di risoluzione dei problemi delle prestazioni come Waits and Queues identifica il motivo dell'elevato consumo di CPU, quindi si può raccomandare un'azione appropriata una volta identificato il collo di bottiglia.


6

SQL Server sta scegliendo un piano diverso nell'altra casella.

Il ripristino in genere rimuove i problemi in base alle statistiche, quindi esaminerei le differenze del server.

Alcuni controlli grossolani prima. Non dare per scontato: controlla

  • Verificare che le impostazioni di SQL Server siano le stesse nella configurazione di sys, ad es. Grado massimo o parallelismo
  • Esegui DBCC USEROPTIONS per vedere se le impostazioni ANSI sono diverse in fase di esecuzione (le impostazioni ANS possono influire sul piano scelto)
  • Controlla i registri di Windows e SQL Server per vedere se ci sono problemi

Quindi salta alla fine, secondo la risposta di Remus.


Grazie per i suggerimenti. Entrambe le configurazioni sys.configurations e DBCC USEROPTIONS sono identiche. Nessun errore o avviso nei registri dei server Windows o SQL.

1
Ed eseguono anche lo stesso layout del database? Nessun piano di amministrazione che esegue ottimizzazioni su (ricostruzione indice ecc.), I database hanno le stesse statistiche per gli oggetti rilevanti e lo stesso layout del disco? Stesso livello di patch?
TomTom,

Sì, stesso disco, layout DB e livello patch. In effetti, il database sulla macchina veloce è un backup ripristinato dalla macchina lenta. E non ci sono piani di amministrazione che variano, per quanto posso vedere.
Ryandenki,

6

Se tutte le altre cose sono uguali, è probabile (secondo la risposta di @ gbn) che su ciascun server venga generato un piano di esecuzione diverso. Come esercizio accademico, sarebbe interessante vedere entrambi i piani, quindi prendili dalla cache dei piani su ciascun server e aggiungili alla tua domanda, se possibile. Possiamo quindi identificare le differenze nei piani che stanno causando una così grande variazione nelle prestazioni.

Per una soluzione rapida, dai un'occhiata al suggerimento USE PLAN . Ciò consente di collegare il buon piano dal server veloce alla procedura memorizzata sul server lento.

Modifica: dopo l'aggiornamento re: cursore

Un'altra variante della tua query per provare che non vedo menzionato in altre risposte:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE NOT EXISTS (SELECT 1 FROM dbo.B WHERE dbo.B.X = dbo.A.X)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y

Questo è un buon consiglio, stiamo controllando i piani di query. In realtà, il rallentamento della procedura memorizzata sembra essere legato a un cursore. Vedi modifica.
Ryandenki,

4

Humor me, e prova a sostituire:

DECLARE C CURSOR FOR
SELECT X, Y
FROM dbo.A
WHERE X NOT IN (SELECT X FROM dbo.B)
AND Z <=0

con questo:

DECLARE C CURSOR FOR
SELECT 
    X, 
    Y
FROM dbo.A

    LEFT OUTER JOIN dbo.B
        ON dbo.A.X = dbo.b.X

WHERE dbo.B.X IS NULL
AND Z <=0

Non penso che questo dovrebbe manifestarsi come un problema di prestazioni nella porzione FETCH NEXT FROM del tuo codice, ma non ho ancora fatto l'iniezione di caffeina. Prova il mio suggerimento e fammi sapere.

Spero che sia di aiuto,

opaco


4

Controlla i tuoi indici e aggiorna tutte le tue statistiche. Ho avuto un problema molto simile al simulatore e si è scoperto che le statistiche su una macchina erano traballanti.


1

Ho provato questo stesso comportamento due volte e ti dirò cosa lo risolve ogni volta:

1.) Ho aggiunto il suggerimento WITH RECOMPILE alla procedura memorizzata perché il piano memorizzato nella cache era terribile.

2.) Ho modificato la procedura memorizzata per utilizzare le tabelle temporanee anziché le variabili di tabella.

Spero che uno di questi aiuti. In bocca al lupo.

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.