Perilaku yang Anda gambarkan sering kali disebabkan oleh rencana kueri yang di-cache salah dan/atau statistik kedaluwarsa.
Ini biasanya terjadi ketika Anda memiliki sejumlah besar parameter dalam klausa WHERE, terutama daftar panjang yang berbentuk:
(@parameter1 is NULL OR TableColumn1 = @parameter1)
Katakanlah, paket kueri yang di-cache kedaluwarsa, dan proc dipanggil dengan serangkaian parameter yang tidak representatif. Paket tersebut kemudian di-cache untuk profil data ini. TETAPI, jika proc lebih sering umum dengan serangkaian parameter yang sangat berbeda, rencananya mungkin tidak sesuai. Ini sering dikenal sebagai 'parameter sniffing'.
Ada beberapa cara untuk mengurangi dan menghilangkan masalah ini tetapi mereka mungkin melibatkan pertukaran dan bergantung pada versi SQL Server Anda. Lihat OPTIMIZE FOR
dan OPTIMIZE FOR UNKNOWN
. JIKA (dan itu besar jika) proc jarang dipanggil tetapi harus berjalan secepat mungkin, Anda dapat menandainya sebagai OPTION(RECOMPILE)
, untuk memaksa kompilasi ulang setiap kali dipanggil, TAPI jangan lakukan ini untuk procs yang sering dipanggil ATAU tanpa penyelidikan.
[CATATAN:perhatikan Paket layanan dan Pembaruan Kumulatif (CU) kotak SQL Server 2008 Anda, karena logika kompilasi ulang dan parameter sniffing bekerja secara berbeda di beberapa versi]
Jalankan kueri ini (dari Glenn Berry) untuk menentukan status statistik:
-- 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);