Làm cách nào để xóa kế hoạch thực thi xấu khỏi Cơ sở dữ liệu Azure SQL?


12

DBCC FREEPROCCACHEkhông hoạt động trong Azure SQL DB. Làm thế nào khác tôi có thể buộc một kế hoạch tự loại bỏ bộ nhớ cache theo cách không làm tổn thương hệ thống sản xuất (ví dụ: tôi không thể thay đổi bảng willy nilly)? Điều này đặc biệt dành cho SQL được tạo bởi Entity Framework, vì vậy đây không phải là các procs được lưu trữ tự quản lý - đó là SQL động hiệu quả.

(Nguồn là các chỉ mục xấu -> số liệu thống kê xấu, v.v ... Tất cả đều cố định, nhưng một kế hoạch tồi sẽ không biến mất.)

CẬP NHẬT: Tôi đã chọn giải pháp của @ mrdenny khi anh ấy đến đó trước. Tuy nhiên, tôi đang sử dụng thành công kịch bản của @Aaron Bertrand để thực hiện công việc. Cảm ơn mọi người đã giúp đỡ !!


Bạn có thể thực hiện một sp_recompile trong Azure không?
mrdenny

Đúng. Chính xác thì tôi sẽ chạy nó vào cái gì? Chúng tôi không có procs lưu trữ. Đây là SQL động chạy trong sp_executesql.
Jaxidian

2
Bạn có thể tự chạy nó trên bàn và nó sẽ xóa các kế hoạch sử dụng bảng đó. (Nếu điều này hoạt động tôi sẽ làm cho nó một câu trả lời.)
mrdenny

1
Tôi vừa thử cái này trên một cái bàn và nó dường như khóa bảng trong một giao dịch trong khi xử lý. Tôi đã thử nó trên một bảng 10 cột chỉ với 24 bản ghi và phải mất hơn một phút để hoàn thành. Trong thời gian này, tôi không thể truy vấn bảng. Tôi không thể chạy một cái gì đó như thế trên các bàn thực sự của chúng tôi trong Sản xuất!
Jaxidian

1
Chết tiệt, đó là một người lập dị. Có vẻ như bạn sẽ cần thực hiện thay đổi lược đồ như thêm một cột không thể, sau đó thả nó. Điều đó cũng sẽ xóa bộ nhớ cache và sẽ nhanh chóng. Kiểm tra sẽ cho chắc chắn.
mrdenny

Câu trả lời:


12

Azure SQL hiện hỗ trợ trực tiếp

Cơ sở dữ liệu Azure SQL trực tiếp hỗ trợ xóa bộ nhớ cache của cơ sở dữ liệu người dùng hiện tại mà không có bất kỳ hack nào:

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

thông tin thêm

Kịch bản sau đây (của Shannon Gowen ) có thể được sử dụng để theo dõi quá trình từng bước:

-- run this script against a user database, not master
-- count number of plans currently in cache
select count(*) from sys.dm_exec_cached_plans;

-- Executing this statement will clear the procedure cache in the current database, which means that all queries will have to recompile.
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

-- count number of plans in cache now, after they were cleared from cache
select count(*) from sys.dm_exec_cached_plans;

-- list available plans
select * from sys.dm_exec_cached_plans;

Tôi chưa thử điều này nhưng nếu đây thực sự là chức năng, thì đây có lẽ là câu trả lời "tốt nhất" vào đầu năm 2017. Cảm ơn vì điều này - tôi không có manh mối nào ở đây! :-)
Jaxidian

Tôi đã thử điều này (trên DB cao cấp) và nó đã hoạt động.
Remi Lemarchand

Tôi đã gắn cờ đây là "Câu trả lời được chấp nhận" cập nhật nhưng tôi chưa tự mình kiểm tra điều này. Tôi đang căn cứ điều này trực tiếp vào phản hồi của Todd và Remi. Cảm ơn tất cả!
Jaxidian

Chỉ cần xem lại, tôi đã sử dụng nó và nó hoạt động tốt cho tôi! Tôi đang thêm một số kịch bản bổ sung vào câu trả lời của Todd ở đây để làm phong phú thêm nhưng bài viết của anh ấy đã đâm vào đầu.
Jaxidian

Điều này dường như không hoạt động đối với tôi - nó chỉ thực thi nhưng danh sách vẫn đầy - tôi đang sử dụng SQL Azure - điều gì có thể sai?
Dirk Boer

12

Hôm nay không có cách rõ ràng để làm điều này, nhưng đó không phải là một kịch bản vĩnh viễn (lệnh DBCC vẫn không được hỗ trợ, nhưng hãy đọc trên Cửa hàng truy vấn ). Ngay cả khi cú đánh thay đổi lược đồ có thể được chấp nhận, nó có thể không phải là điều bạn muốn, bởi vì nó sẽ làm mất hiệu lực tất cả các kế hoạch liên quan đến đối tượng cơ bản, không chỉ là kế hoạch xấu.

Không tìm kiếm tín dụng cho việc này, nhưng xây dựng SQL động để thực hiện cùng một hoạt động đối với nhiều bảng khá dễ dàng:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE '
  + QUOTENAME(SCHEMA_NAME([schema_id])) 
  + '.' + QUOTENAME(name) + ' ADD fake_column INT NULL;
  ALTER TABLE ' 
  + QUOTENAME(SCHEMA_NAME([schema_id]))
  + '.' + QUOTENAME(name) + ' DROP COLUMN fake_column;'
FROM sys.tables
--WHERE name IN, LIKE, etc.

PRINT @sql;

-- if the command > 8K, you can see the second chunk e.g.

PRINT SUBSTRING(@sql, 8001, 8000);

--EXEC sys.sp_executesql @sql;

(Tôi đã viết một mẹo về vấn đề "độ dài SQL động" này ...)


Trong trường hợp của tôi, loại bỏ tất cả chúng là tốt hơn nhiều để lại những cái xấu trong đó. Cảm ơn cho những người đứng đầu lên. Tôi biết bạn không thể cho tôi biết các tính năng nhưng bạn có thể cho tôi biết khi nào bạn có thể không còn bị hạn chế khi nói về những điều bạn không thể nói về? ;-)
Jaxidian

Đó cũng là phân loại, xin lỗi. :-)
Aaron Bertrand

Không chắc chắn những gì bạn có nghĩa là liên kết. Ý tôi là nvarchar(max)biến của bạn đạt đến giới hạn sau 4000 ký tự, 8000 ký tự nếu tôi thay đổi thành varchar(max). Chạy kịch bản chính xác đó. Chúng tôi có ~ 450 bảng, vì vậy chúng tôi dễ dàng đạt được điều đó (~ 30/60 bảng). varchar(max)là cú pháp hợp lệ, nó chỉ giống hệt varchar(8000)nvarchar(max)giống hệt với nvarchar(4000).
Jaxidian

3
Vâng, khi bạn PRINTlệnh, nó chỉ hiển thị 8000 byte. Đó là một hạn chế của PRINTlệnh, không phải Azure. Nếu bạn chạy lệnh, nó sẽ hoạt động ngay cả khi bạn không thể kiểm tra trực quan toàn bộ.
Aaron Bertrand

... doh, xin lỗi, tôi nghĩ bạn đúng! Cảm ơn vì đã sửa tôi! Đó là những gì xảy ra khi vợ bạn mong đợi bạn rời đi 25 phút trước ... ;-) Kịch bản này hoạt động hoàn hảo với tôi!
Jaxidian

6

Thêm một cột nullable vào bảng sau đó thả cột. Điều đó sẽ buộc SQL xóa bộ đệm cho đối tượng đó.

Đối với việc thực hiện tất cả các bảng, một con trỏ sẽ thực hiện thủ thuật. Chỉ cần sử dụng tên cột sẽ không bao giờ tồn tại trong bất kỳ bảng nào như 'zzzzzz_go_away' hoặc một cái gì đó.


4

Cơ sở dữ liệu Azure SQL hiện không hỗ trợ DBCC FREEPROCCACHE, do đó bạn không thể xóa kế hoạch thực hiện thủ công khỏi bộ đệm. Tuy nhiên, nếu bạn thay đổi bảng hoặc dạng xem được tham chiếu bởi truy vấn ( ALTER TABLE/ ALTER VIEW), gói sẽ bị xóa khỏi bộ đệm. ( Tham khảo .)


Tôi đã biết tất cả mọi thứ bạn đăng ở đây. Đây không phải là một thủ tục được lưu trữ cũng như một khung nhìn, vì vậy tôi không thể sửa đổi một trong những thủ tục đó. Làm cách nào tôi có thể sửa đổi các bảng của mình theo cách không đáng kể, trong khi đang tải và không gây ra bất kỳ thời gian chết hoặc khóa nào của bảng, để kích hoạt điều này?
Jaxidian

1
Bạn có thể có thể thêm một cột giả và sau đó thả nó. Điều này sẽ loại bỏ kế hoạch từ bộ đệm. Cái bàn to cỡ nào?
Kin Shah

Điều đó đã trở thành giải pháp, theo khuyến nghị của @mrdenny. Cảm ơn đã giúp đỡ!! :-)
Jaxidian

1
Cảm ơn ... Chỉ vài giây ngắn ngủi .. ​​Đã trả lời một số bài đăng khác trên stackexchange ...
Kin Shah

1

Để xóa tất cả các kế hoạch thực hiện, sử dụng này:

    SET NOCOUNT ON

DECLARE @lcl_name VARCHAR(100)
DECLARE @addcolumnSql nVARCHAR(MAX)
DECLARE @dropcolumnSql nVARCHAR(MAX)

DECLARE cur_name CURSOR FOR
SELECT name
FROM sysobjects
WHERE type = 'U'
OPEN cur_name
FETCH NEXT FROM cur_name INTO @lcl_name
WHILE @@Fetch_status = 0
BEGIN
set @addcolumnSql = 'alter table [' + @lcl_name + '] add temp_col_to_clear_exec_plan bit'
EXEcute sp_executesql @addcolumnSql
print @addcolumnSql
set @dropcolumnSql = 'alter table [' + @lcl_name + '] drop column temp_col_to_clear_exec_plan'
EXEcute sp_executesql @dropcolumnSql
print @dropcolumnSql
--  EXEC (@lcl_name )
FETCH NEXT FROM cur_name INTO @lcl_name
END
CLOSE cur_name
DEALLOCATE cur_name
SET NOCOUNT OFF

Nếu bạn thay đổi bảng hoặc xem tham chiếu đến nó, kế hoạch thực hiện sẽ bị xóa.

Giải thích thêm một chút ở đây http://christianarg.wordpress.com/2013/08/22/remove-execut-plans-from-the-procedure-cache-in-sql-azure/

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.