Azure SQL Database에서 잘못된 실행 계획을 제거하려면 어떻게해야합니까?


12

DBCC FREEPROCCACHEAzure SQL DB에서 작동하지 않습니다. 프로덕션 시스템에 해를 끼치 지 않는 방식으로 계획을 캐시에서 강제로 쫓아 낼 수있는 방법은 무엇입니까? 이것은 특히 Entity Framework에서 생성 한 SQL을위한 것이므로 자체 관리 저장 프로 시저가 아닙니다. 효과적으로 동적 SQL입니다.

(소스는 잘못된 인덱스-> 나쁜 통계 등이었습니다. 모두 수정되었지만 잘못된 계획은 사라지지 않습니다.)

업데이트 : 처음에 @mrdenny의 솔루션을 선택했습니다. 그러나 @Aaron Bertrand의 스크립트를 성공적으로 사용하여 작업을 수행하고 있습니다. 도움을 주신 모든 분들께 감사드립니다 !!


Azure에서 sp_recompile을 수행 할 수 있습니까?
mrdenny

예. 정확히 무엇을 실행합니까? 저장된 procs가 없습니다. 이것은에서 실행 된 동적 SQL입니다 sp_executesql.
Jaxidian

2
자체 테이블에서 실행할 수 있으며 해당 테이블을 사용하는 계획을 플러시해야합니다. (이것이 효과가 있다면 답을 드리겠습니다.)
mrdenny

1
방금 테이블에서 시도했지만 처리하는 동안 트랜잭션에서 테이블을 잠급니다. 24 개 레코드 만있는 10 열 테이블에서 시도했지만 완료하는 데 1 분이 걸렸습니다. 이 시간 동안 테이블을 쿼리 할 수 ​​없습니다. 프로덕션의 실제 테이블에서 이와 같은 것을 실행할 수 없습니다!
Jaxidian

1
젠장, 그거 엉망이야 nullable 열 추가와 같은 스키마 변경을 수행 한 다음 삭제해야 할 것 같습니다. 캐시도 지워질 것이고 빠를 것입니다. 테스트가 확실합니다.
mrdenny

답변:


12

Azure SQL은 이제 이것을 직접 지원합니다

Azure SQL Database는 해킹없이 현재 사용자 데이터베이스의 proc 캐시 지우기를 직접 지원합니다.

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

추가 정보

다음 스크립트 ( Shannon Gowen )는 프로세스를 단계별로 감시하는 데 사용할 수 있습니다.

-- 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;

나는 이것을 아직 시도하지 않았지만 이것이 실제로 기능적이라면 아마도 2017 년 초 현재 "최고의"답변 일 것입니다. 이것에 대해 감사드립니다-이것이 거기에 실마리가 없었습니다! :-)
Jaxidian

나는 이것을 프리미엄 DB에서 시도했지만 효과가있었습니다.
Remi Lemarchand

업데이트 된 "승인 된 답변"으로 플래그를 지정했지만 아직이 테스트를하지 않았습니다. 나는 이것을 Todd와 Remi의 피드백에 직접 기초하고 있습니다. 모두 감사합니다!
Jaxidian

다시 방문하기 위해 이것을 사용했으며 잘 작동했습니다! Todd의 답변에 스크립트를 추가하여 풍부하게하지만 그의 게시물은 머리에 못을 박았습니다.
Jaxidian

이것은 나를 위해 작동하지 않는 것 같습니다-그냥 실행되지만 목록이 여전히 가득합니다-SQL Azure에 있습니다-무엇이 잘못 될 수 있습니까?
Dirk Boer 19

12

오늘이 작업을 수행하는 명확한 방법은 없지만 영구적 인 시나리오는 아닙니다 (DBCC 명령은 여전히 ​​지원되지 않지만 Query Store 에서 읽습니다 ). 스키마 변경 적중이 허용되는 경우에도 기본 오브젝트와 관련된 모든 계획 이 무효화되지 않기 때문에 원하는 변경이 불가능할 수 있습니다 .

이것에 대한 크레딧을 찾지 않고 여러 테이블에 대해 동일한 작업을 수행하기 위해 동적 SQL을 작성하는 것은 매우 쉽습니다.

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;

( 이 "길이의 동적 SQL"문제에 대한 팁을 썼습니다 ...)


내 경우에는, 그것들을 모두 제거하는 것이 나쁜 것을 남겨 두는 것이 훨씬 바람직합니다. 고마워요 나는 당신이 나를 기능을 말할 수 없다 알고 있지만 당신은 말해 줄 수 없다 당신은 더 이상 이야기 할 수없는 것들에 대해 이야기에 대해 제한 할 수 있는가? ;-)
Jaxidian

그것은 또한 분류됩니다, 죄송합니다. :-)
Aaron Bertrand

링크의 의미가 확실하지 않습니다. 내가 의미하는 바는 nvarchar(max)변수를으로 변경하면 4000 자, 8000 자 후에 제한에 도달한다는 것 varchar(max)입니다. 정확한 스크립트를 실행합니다. 우리는 ~ 450 개의 테이블을 가지고 있으므로 쉽게 맞출 수 있습니다 (~ 30 / 60 테이블). varchar(max)유효한 구문이며 varchar(8000)nvarchar(max)동일하며 동일합니다 nvarchar(4000).
Jaxidian

3
네, PRINT명령을 내리면 8000 바이트 만 표시됩니다. 이것이 PRINTAzure가 아닌 명령 의 제한 사항입니다 . 명령을 실행하면 전체를 육안으로 검사 할 수 없더라도 작동합니다.
Aaron Bertrand

... 죄송합니다, 당신 말이 맞아요! 수정 해 주셔서 감사합니다. 아내가 25 분 전에 떠날 것을 기대했을 때 일어난 일입니다. ;-)이 스크립트는 저에게 완벽하게 작동합니다!
Jaxidian

6

테이블에 널 입력 가능 열을 추가 한 후 삭제하십시오. 그러면 SQL이 해당 객체의 캐시를 플러시해야합니다.

모든 테이블을 수행하는 경우 커서가 트릭을 수행해야합니다. 'zzzzzz_go_away'와 같은 테이블에는 존재하지 않는 열 이름 만 사용하십시오.


4

Azure SQL Database는 현재을 지원하지 않으므로 DBCC FREEPROCCACHE캐시에서 실행 계획을 수동으로 제거 할 수 없습니다. 그러나 쿼리 ( ALTER TABLE/ ALTER VIEW)가 참조하는 테이블 또는 뷰를 변경 하면 계획이 캐시에서 제거됩니다. ( 참고 .)


나는 당신이 여기에 게시 한 모든 것을 이미 알고있었습니다. 이것은 저장 프로 시저 또는 뷰가 아니므로 그 중 하나를 수정할 수 없습니다. 로드 중일 때와 테이블의 다운 타임이나 잠금을 유발하지 않으면 서 테이블을 무의미하게 수정하려면 어떻게해야합니까?
Jaxidian

1
더미 열을 추가 한 다음 놓을 수 있습니다. 캐시에서 계획이 제거됩니다. 테이블이 얼마나 큽니까?
Kin Shah

@mrdenny가 권장하는대로 솔루션이되었습니다. 도와 주셔서 감사합니다!! :-)
Jaxidian

1
고마워 ... 단순 몇 초 짧은 .. stackexchange에 대한 다른 게시물에 대답했다 ...
Kin Shah

1

모든 실행 계획을 지우려면 다음을 사용하십시오.

    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

이를 참조하는 테이블이나 뷰를 변경하면 실행 계획이 지워집니다.

여기에 조금 더 설명되어 있습니다 http://christianarg.wordpress.com/2013/08/22/remove-execution-plans-from-the-procedure-cache-in-sql-azure/

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.