ฉันจะลบแผนไม่ถูกต้องเฉพาะออกจากแคชแบบสอบถาม SQL Server ได้อย่างไร


33

เรามีแบบสอบถาม SQL Server 2008 หนึ่งรายการ (ไม่ใช่ proc ที่เก็บไว้ แต่เป็นสตริง SQL เดียวกัน - ดำเนินการทุก 5 นาที) ที่เก็บแคชแผนแบบสอบถามที่ไม่ดีเป็นระยะ ๆ

โดยปกติแบบสอบถามนี้จะทำงานในไม่กี่มิลลิวินาที แต่ด้วยแผนแบบสอบถามที่ไม่ดีนี้จะใช้เวลา 30+ วินาที

ฉันจะลบแผนการสอบถามแคชที่ไม่ถูกต้องออกจาก SQL Server 2008 ได้อย่างไรโดยไม่ต้องล้างแคชคิวรีทั้งหมดบนเซิร์ฟเวอร์ฐานข้อมูลการผลิต


คำตอบ:


39

ฉันหาสิ่งเล็ก ๆ น้อย ๆ

select * from sys.dm_exec_query_stats

จะแสดงแผนการสืบค้นที่แคชทั้งหมด น่าเสียดายที่ไม่มีข้อความ SQL ปรากฏอยู่ที่นั่น

อย่างไรก็ตามคุณสามารถเข้าร่วมข้อความ SQL กับแผนดังนี้:

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

จากที่นี่มันค่อนข้างง่ายที่จะเพิ่มส่วนWHEREคำสั่งเพื่อค้นหา SQL ที่ฉันรู้ว่าอยู่ในแบบสอบถามและจากนั้นฉันสามารถดำเนินการได้:

DBCC FREEPROCCACHE (plan_handle_id_goes_here)

เพื่อลบแผนแบบสอบถามแต่ละรายการออกจากแคชแผนแบบสอบถาม ไม่ใช่ว่าง่ายหรือสะดวก แต่ดูเหมือนว่าจะใช้งานได้ ..

แก้ไข: ทิ้งแคชแบบสอบถามทั้งหมดจะทำงานและมีอันตรายน้อยกว่ามันฟังอย่างน้อยในประสบการณ์ของฉัน:

DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL;

2
คำแนะนำในการใช้คำใบ้แผนไม่ย่อท้อ
Remus Rusanu

1
ฉันพบสิ่งนี้หลังจากข้อความค้นหาของฉันรีเฟรชอย่างน่าอัศจรรย์มันเป็นแผนไม่ดี แต่ฉันวางแผนที่จะทดสอบในครั้งต่อไป คำใบ้แผนไม่ได้ช่วยอะไรถ้าแบบสอบถามมีปัญหาจาก 'optional-itis' - ซึ่งมีพารามิเตอร์ที่เป็นตัวเลือกมากมายและได้รับการปรับให้เหมาะสมสำหรับชุดเดียวจากนั้นเรียกใช้ชุดอื่น ไม่มีแผนที่ดีที่สุดที่สามารถแนบสำหรับแบบสอบถามชนิดนี้ มีแผนที่ดีที่สุดสำหรับชุดพารามิเตอร์หนึ่งชุดซึ่งแย่มากสำหรับพารามิเตอร์ชุดอื่น
Nick.McDermaid

6

ถ้าคุณรู้วิธีการวางแผนที่ดีดูเหมือนว่าเพียงแค่ใช้คำใบ้แผน

คุณไม่สามารถลบรายการแคชเฉพาะ DBCC FREESYSTEMCACHE(cachename/poolname)แต่คุณสามารถทำความสะอาดสระว่ายน้ำแคชทั้งหมดที่มี

คุณสามารถรับชื่อแคชของแผนแบบสอบถามที่ไม่ถูกต้องหากคุณมีหมายเลขอ้างอิงแผน (จากsys.dm_exec_requests.plan_handleสำหรับ session_id มีปัญหาระหว่างการดำเนินการหรือจากsys.dm_exec_query_statsดำเนินการโพสต์):

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

อย่างไรก็ตามแผน SQL ทั้งหมดมีชื่อ 'แผนการ SQL' ซึ่งทำให้การเลือกหนึ่งที่เหมาะสมสำหรับ DBCC FREESYSTEMCACHE a ... ทางเลือกที่ยาก

ปรับปรุง

ไม่เป็นไรลืมไปDBCC FREEPROCCACHE(plan_handle)แล้วใช่ว่าจะได้ผล


1
ความสามารถในการส่ง plan_handle ไปยัง DBCC FREEPROCCACHE นั้นมีอยู่ใน SQL Server 2008 และไม่ได้อยู่ใน SQL Server 2005
Mario

มันหมายความว่าอะไรถ้าsys.dm_exec_cached_plansมีรายการในมันไม่มีสำหรับplan_handleจากsys.dm_exec_requests?
Jonathan Gilbert

@JonathanGilbert หมายความว่าแผนไม่ได้ถูกแคชหรือถูกไล่ออกจากแคช ดูdocs.microsoft.com/en-us/sql/relational-database/…
Remus Rusanu

ดังนั้นเพื่อยืนยันแม้ว่าฉันเพิ่งจะเริ่มต้นใช้งานคิวรีนั้นและเคียวรีไม่ได้บอกว่าไม่แคช แต่สามารถ uncached ได้เนื่องจาก SQL Server ตัดสินใจที่จะไม่ใช้แคชหรือไม่ มันจะไม่เป็นเพราะมันยังทำงานอยู่ใช่มั้ย ถ้ามันตัดสินใจที่จะแคชแผนแล้วมันจะถูกแคชจากจุดที่แบบสอบถามเริ่มทำงาน?
Jonathan Gilbert

1

FREEPROCCACHEแก้ปัญหาคือดี แต่ทางตรงมากขึ้นของการทำเช่นนี้คือการใช้OPTION (RECOMPILE)ใน SQL String (คุณกล่าวถึงมันไม่ได้ขึ้นเครื่องหมาย SP) นี้จะบอกเครื่องยนต์แผนเดี่ยวใช้มันเพราะมีแนวโน้มที่คุณสงสัย มีพารามิเตอร์ดมกลิ่นหรือสถิติของคุณแตกต่างอย่างมากจากการทำงานเพื่อเรียกใช้และคุณสงสัยว่ามันเป็นปัญหาแผนแคชที่ไม่ดี

DECLARE @SQL NVARCHAR(4000)
SELECT @SQL = 'SELECT * FROM Table WHERE Column LIKE @NAME OPTION (RECOMPILE)'
EXEC sp_executesql @SQL, N'@NAME varchar(15)', 'MyName' 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.