Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Problemi di prestazioni intermittenti della funzione SQL Server

Il comportamento che descrivi è spesso dovuto a un piano di query memorizzato nella cache in modo errato e/o a statistiche non aggiornate.

Si verifica comunemente quando si dispone di un numero elevato di parametri in una clausola WHERE, in particolare un lungo elenco di quelli che hanno la forma:

(@parameter1 is NULL OR TableColumn1 = @parameter1)

Supponiamo che il piano di query memorizzato nella cache scada e il processo venga chiamato con un insieme di parametri non rappresentativo. Il piano viene quindi memorizzato nella cache per questo profilo dati. MA, se il proc è più spesso comune con un insieme di parametri molto diverso, il piano potrebbe non essere appropriato. Questo è spesso noto come "sniffing dei parametri".

Esistono modi per mitigare ed eliminare questo problema, ma possono comportare compromessi e dipendono dalla versione di SQL Server in uso. Guarda OPTIMIZE FOR e OPTIMIZE FOR UNKNOWN . SE (ed è un grande se) il proc viene chiamato raramente ma deve essere eseguito il più velocemente possibile, puoi contrassegnarlo come OPTION(RECOMPILE) , per forzare una ricompilazione ogni volta che viene chiamato, MA non farlo per processi chiamati frequentemente O senza indagine.

[NOTA:tieni presente quale Service pack e aggiornamento cumulativo (CU) la tua casella di SQL Server 2008 ha, poiché la logica di ricompilazione e di sniffing dei parametri funziona in modo diverso in alcune versioni]

Esegui questa query (da Glenn Berry) per determinare lo stato delle statistiche:

-- When were Statistics last updated on all indexes?
SELECT o.name, i.name AS [Index Name],  
      STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date], 
      s.auto_created, s.no_recompute, s.user_created, st.row_count
FROM sys.objects AS o WITH (NOLOCK)
INNER JOIN sys.indexes AS i WITH (NOLOCK)
ON o.[object_id] = i.[object_id]
INNER JOIN sys.stats AS s WITH (NOLOCK)
ON i.[object_id] = s.[object_id] 
AND i.index_id = s.stats_id
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK)
ON o.[object_id] = st.[object_id]
AND i.[index_id] = st.[index_id]
WHERE o.[type] = 'U'
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE);