Làm cách nào để xóa một gói xấu cụ thể khỏi bộ đệm truy vấn SQL Server?


33

Chúng tôi có một truy vấn SQL Server 2008 cụ thể (không phải là một Proc được lưu trữ, nhưng cùng một chuỗi SQL - thực hiện cứ sau 5 phút) liên tục lưu trữ một kế hoạch truy vấn rất tệ.

Truy vấn này thường chạy trong vài mili giây, nhưng với gói truy vấn xấu này, phải mất hơn 30 giây.

Làm cách nào để tôi phẫu thuật loại bỏ chỉ một kế hoạch truy vấn được lưu trong bộ nhớ cache xấu khỏi SQL Server 2008 mà không xóa toàn bộ bộ đệm truy vấn trên máy chủ cơ sở dữ liệu sản xuất?


Câu trả lời:


39

Tôi đã tìm ra một vài điều

select * from sys.dm_exec_query_stats

sẽ hiển thị tất cả các kế hoạch truy vấn được lưu trữ. Thật không may, không có văn bản SQL được hiển thị ở đó.

Tuy nhiên, bạn có thể nối văn bản SQL vào các kế hoạch như vậy:

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

Từ đây, việc thêm một WHEREmệnh đề để tìm SQL mà tôi biết là trong truy vấn, và sau đó tôi có thể thực hiện:

DBCC FREEPROCCACHE (plan_handle_id_goes_here)

để loại bỏ từng gói truy vấn khỏi bộ đệm kế hoạch truy vấn. Không chính xác dễ dàng hoặc thuận tiện, nhưng nó có vẻ hoạt động ..

chỉnh sửa: bỏ toàn bộ bộ đệm truy vấn cũng sẽ hoạt động và ít nguy hiểm hơn âm thanh, ít nhất là theo kinh nghiệm của tôi:

DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL;

2
lời khuyên để sử dụng một gợi ý kế hoạch là không ít.
Remus Rusanu

1
Tôi đã tìm thấy điều này sau khi truy vấn của tôi làm mới một cách kỳ diệu đó là kế hoạch tồi tệ nhưng tôi dự định thử nghiệm lần sau. Một gợi ý về kế hoạch không giúp ích gì nếu truy vấn bị 'tùy chọn' - nơi nó có nhiều tham số tùy chọn và nó đã được tối ưu hóa cho một bộ, sau đó chạy cho một bộ khác. Không có kế hoạch tối ưu có thể được đính kèm cho loại truy vấn này. Có một kế hoạch tối ưu cho một bộ thông số lần lượt là khủng khiếp cho một bộ thông số khác.
Nick.McDilyn

6

Nếu bạn biết kế hoạch tốt trông như thế nào, chỉ cần sử dụng một gợi ý kế hoạch .

Bạn không thể xóa một mục bộ đệm cụ thể, nhưng bạn có thể xóa toàn bộ nhóm bộ đệm DBCC FREESYSTEMCACHE(cachename/poolname).

Bạn có thể nhận được tên bộ đệm của kế hoạch truy vấn xấu nếu bạn có xử lý kế hoạch (từ sys.dm_exec numquests.plan_handle cho session_id gặp rắc rối trong khi thực hiện hoặc từ sys.dm_exec_query_stats thực thi bài đăng):

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

Tuy nhiên, tất cả các gói SQL đều có tên 'Kế hoạch SQL', điều này khiến cho việc chọn đúng kế hoạch cho DBCC FREESYSTEMCACHE là một ... sự lựa chọn khó khăn.

Cập nhật

Nevermind, quên về DBCC FREEPROCCACHE(plan_handle), có sẽ làm việc.


1
Khả năng chuyển plan_handle cho DBCC FREEPROCCACHE có sẵn trong SQL Server 2008 và không có trong SQL Server 2005.
Mario

Điều đó có nghĩa là gì nếu sys.dm_exec_cached_planskhông có mục nào trong đó cho plan_handletừ sys.dm_exec_requests?
Jonathan Gilbert

@JonathanGilbert điều đó có nghĩa là kế hoạch không được lưu trong bộ nhớ cache hoặc bị xóa khỏi bộ đệm. Xem docs.microsoft.com/en-us/sql/relational-database/ triệt
Remus Rusanu

Vì vậy, chỉ để xác nhận, mặc dù tôi chỉ mới bắt đầu chạy truy vấn đó và truy vấn không có gợi ý nào nói không lưu vào bộ đệm, nhưng nó có thể bị xóa vì SQL Server đưa ra quyết định giá trị không lưu bộ đệm không? Không phải là vì nó vẫn chạy, phải không? Nếu nó quyết định lưu trữ kế hoạch, thì nó sẽ được lưu vào bộ nhớ cache ngay từ điểm truy vấn bắt đầu chạy?
Jonathan Gilbert

1

Các FREEPROCCACHE giải pháp là tốt, nhưng một cách trực tiếp hơn để làm điều này là sử dụng OPTION (biên dịch lại) trên SQL Chuỗi của bạn (bạn đề cập đến nó không phải là một SP), điều này nói với Engine một kế hoạch Single Use nó, bởi vì khả năng bạn nghi ngờ Có Thông số Đánh hơi hoặc Số liệu thống kê của bạn khác biệt nhiều so với chạy để chạy và bạn nghi ngờ đó là vấn đề về Bộ nhớ đệm xấu.

DECLARE @SQL NVARCHAR(4000)
SELECT @SQL = 'SELECT * FROM Table WHERE Column LIKE @NAME OPTION (RECOMPILE)'
EXEC sp_executesql @SQL, N'@NAME varchar(15)', 'MyName' 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.