Belirli bir kötü planı SQL Server sorgu önbelleğinden nasıl kaldırırım?


33

Belirli bir SQL Server 2008 sorgumuz var (saklı bir proc değil, aynı SQL string - her 5 dakikada bir çalıştırılıyor) ve zaman zaman çok kötü bir sorgu planını önbelleğe alıyor.

Bu sorgu normalde birkaç milisaniyede yayınlanır, ancak bu hatalı sorgu planında 30+ saniye sürer.

Üretim veritabanı sunucusundaki tüm sorgu önbelleğini atmadan, yalnızca bir kötü önbelleğe alınmış sorgu planını SQL Server 2008'den nasıl kaldırabilirim ?


Yanıtlar:


39

Birkaç şey buldum

select * from sys.dm_exec_query_stats

Tüm önbelleğe alınmış sorgu planlarını gösterecektir. Ne yazık ki, orada hiçbir SQL metni gösterilmez.

Ancak, SQL metnini aşağıdaki gibi planlara birleştirebilirsiniz:

select plan_handle, creation_time, last_execution_time, execution_count, qt.text
FROM 
   sys.dm_exec_query_stats qs
   CROSS APPLY sys.dm_exec_sql_text (qs.[sql_handle]) AS qt

Buradan WHEREsorguda olduğunu bildiğim SQL'i bulmak için bir cümle eklemek oldukça önemsizdir ve sonra yürütebilirim:

DBCC FREEPROCCACHE (plan_handle_id_goes_here)

Her sorgu planını sorgu planı önbelleğinden kaldırmak için. Tam olarak kolay ya da rahat değil, ama işe yarayacak gibi görünüyor .

edit: tüm sorgu önbelleğini boşaltmak da işe yarayacak ve en azından benim deneyimimde göründüğünden daha az tehlikeli:

DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL;

2
Bir plan ipucu kullanma önerileri hiçbiri daha az değildir.
Remus Rusanu,

1
Bunu sorgunun sihirli bir şekilde kötü bir plana göre yenilenmesinden sonra buldum ama bir dahaki sefere test etmeyi düşünüyorum. Sorgu 'isteğe bağlı-itis' den muzdaripse bir plan ipucu yardımcı olmaz - burada birçok isteğe bağlı parametrenin bulunduğu ve bir küme için optimize edildiği, sonra farklı bir küme için çalıştırıldığı. Bu tür bir sorgu için eklenebilecek en uygun plan yoktur. Bir parametre seti için, başka bir parametre grubu için korkunç olan en uygun plan vardır.
Nick.McDermaid, 24:15

6

İyi planın nasıl göründüğünü biliyorsanız, sadece bir plan ipucu kullanın .

Belirli bir önbellek girişini kaldıramazsınız, ancak ile tüm önbellek havuzunu temizleyebilirsiniz DBCC FREESYSTEMCACHE(cachename/poolname).

Plan tanıtıcısına sahipseniz ( yürütme sırasında sorunlu oturum_deni için sys.dm_exec_requests.plan_handle'dan veya yürütme sırasında sys.dm_exec_query_stats sonrası) , hatalı bir sorgu planının önbellek adını alabilirsiniz.

select ce.name
from sys.dm_exec_cached_plans cp
join sys.dm_os_memory_cache_entries ce on cp.memory_object_address = ce.memory_object_address
where cp.plan_handle = @bad_plan

Ancak tüm SQL planları, DBCC FREESYSTEMCACHE için doğru seçimi yapmayı zorlaştıran bir seçim yapan 'SQL Plans' ismine sahiptir.

Güncelleştirme

Boş ver, unutmuş DBCC FREEPROCCACHE(plan_handle), işe yarayacak.


1
Bir plan_handle'ı DBCC FREEPROCCACHE'e geçirme yeteneği SQL Server 2008'de ve SQL Server 2005'te mevcut değildir.
Mario

Eğer bu ne anlama gelir sys.dm_exec_cached_plansiçin içinde hiçbir kayıt yok plan_handledan sys.dm_exec_requests?
Jonathan Gilbert,

@JonathanGilbert, planın önbelleğe alınmadığı veya önbellekten çıkarıldığı anlamına gelir. Bakınız docs.microsoft.com/en-us/sql/relational-databases/…
Remus

Yani sadece onaylamak için, bu sorguyu çalıştırmaya yeni başladım ve sorgunun önbelleğe almamanın bir ipucu olmadığını söylememe rağmen, SQL Server bunu önbelleğe almamaya karar verdi çünkü önbelleklenebilir mi? Olmayacak çünkü hala çalışıyor, değil mi? Planı önbelleğe almaya karar verirse, sorgunun çalışmaya başladığı noktadan itibaren önbelleğe alınır mı?
Jonathan Gilbert,

1

FREEPROCCACHE çözüm iyidir, ama bunu yapmanın daha doğrudan bir yol kullanmaktır OPTION (RECOMPILE) olasılıkla şüpheli çünkü (bunu SP değildi sözü) SQL String üzerinde, bu, Engine onun bir Tek Kullanımlık planını anlatır Parametre Koklama var ya da İstatistikleriniz koşmaktan büyük ölçüde farklı ve Kötü Önbelleğe Alınmış Plan sorunundan şüpheleniyorsunuz.

DECLARE @SQL NVARCHAR(4000)
SELECT @SQL = 'SELECT * FROM Table WHERE Column LIKE @NAME OPTION (RECOMPILE)'
EXEC sp_executesql @SQL, N'@NAME varchar(15)', 'MyName' 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.