저장된 Proc에 대한 갑자기 느린 실행 계획


15

우리는 SQL Server 2000과 관련된 문제를 이해하려고 노력하고 있습니다. 우리는 적당히 거래하는 웹 사이트이며 sp_GetCurrentTransactionscustomerID와 두 날짜를 허용하는 저장 프로 시저 가 있습니다.

이제 날짜와 고객에 따라이 쿼리는 0에서 1000의 행을 반환 할 수 있습니다.

문제 : 우리가 경험 한 것은 갑자기 Execution Timeout Expired특정 클라이언트에 대해 저장된 proc을 실행하려고 시도하는 동안 많은 오류 (일반적으로 또는 유사한) 가 발생 한다는 것입니다. 따라서 쿼리를 검사하고 SSMS에서 실행 한 후 30 초가 걸린다는 것을 알았습니다. 따라서 저장된 proc과 -bang-을 다시 컴파일하여 300ms 내에 실행됩니다.

나는 이것에 대해 DBA와 이야기했다. 그는 저장 프로 시저를 만들 때 데이터베이스가 쿼리 계획을 만들었습니다. 그는 해당 매개 변수 세트에 대한 좋은 계획이라고 말했지만 특정 매개 변수 세트를 처리하면 계획이 해당 데이터에 가장 적합한 계획이 아니므로 느리게 실행되는 것을 볼 수 있습니다.

나에게 제시된 옵션은 저장된 proc에서 해당 쿼리를 이동 계획마다 실행 계획이있는 동적 SQL로 다시 옮기는 것입니다.

이것은 나에게 한 걸음 물린 것처럼 느껴 지며이 주위에 방법이 있어야한다고 생각합니다. 이 문제를 처리 할 다른 방법이 있습니까?

모든 답변을 부탁드립니다.


proc에 if / else 문이 있습니까? 계획이 if 문에 캐시 된 다음 잘못된 계획을 사용하여 else 블록에서 실행하려고 할 때 이런 일이 발생했습니다. 이 오류가 프로세스 변경과 일치 했습니까?
Jeremy Gray

@Jeremy : proc에 변경 사항이 없으며 else / if 문이 없습니다.
Ciaran Archer

답변:


14

이 문제를 매개 변수 스니핑이라고합니다.

최신 버전의 SQL Server는 힌트 OPTION (RECOMPILE)OPTIMIZE FOR힌트 등을 처리 할 수있는 더 많은 옵션을 제공합니다 .

저장 프로 시저에서 변수를 선언하여 매개 변수 값을 변수에 할당하고 대부분의 경우 합리적으로 만족스러운 계획을 얻는 것처럼 들리는 것처럼 매개 변수 대신 변수를 사용하려고 할 수 있습니다.

일반적으로 가장 치명적으로 나쁜 계획은 선택성이 매우 높은 매개 변수에 대해 컴파일되었지만 선택성이 낮은 매개 변수로 실행 된 계획입니다.

생성 된 계획이이 접근 방식으로보다 강력하고 모든 매개 변수 값에 만족한다고 가정하면 JNK가 제안한 것보다이 접근 방식의 장점은 모든 호출에 대해 컴파일 비용이 발생하지 않는다는 것입니다.

단점은 일부 실행의 경우 런타임이 해당 매개 변수 값에 맞게 특별히 계획된 계획보다 클 수 있으므로 컴파일 시간과 실행 시간의 균형을 유지한다는 것입니다.


3
또는 Oracle 용어로 "바인드 바인드"
Gaius

감사합니다 @Gaius, 둘 이상의 RDBMS에 대한 용어를 아는 것이 좋습니다;)
Andrei Rînea

6

동적 SQL을 사용하는 대신 항상 proc 호출을 다음과 같이 변경할 수 있습니다.

EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE

WITH RECOMPILE힘은 (당신이 그것을 짐작!)가 실행 될 때마다 실행 계획의 재 컴파일.

WITH RECOMPILE저장된 proc의 정의에 포함시킬 수도 있습니다 .

CREATE PROCEDURE usp.MyProcedure (Parameters)
WITH RECOMPILE
AS
...

2

옵티 마이저와 약간 싸울 것이지만 사용하려는 데이터베이스를 결정하려고 시도 할 수 있으므로 원하는 것보다 부서지기 쉽습니다.

기술은 이것입니다-저장 프로 시저를 2 개의 매개 변수로 나누십시오. 하나는 하나의 매개 변수 집합을 의미하고 다른 하나는 다른 매개 변수 집합을 의미합니다. 그들 사이에 가능한 모든 경우를 다루도록 where 절을 추가하십시오. 쿼리 계획을 살펴보십시오. 하나는 하나의 매개 변수 세트에 최적화되고 다른 하나는 다른 세트에 최적화되어야합니다. 이 작업을 수행하기 위해 쿼리를 수정해야 할 수도 있고, 쿼리를 수행 할 수 없을 수도 있습니다.이 경우이 방법이 작동하지 않습니다.

이제 원래 스토어드 프로 시저가 매개 변수 값을 확인하고 이전 단락의 두 스토어드 프로 시저 중 적절한 하나에 디스패치하십시오.

이것은 작동 할 수 있지만 최적화 프로그램이 쿼리에 대해보다 효과적으로 작동하게하는 것은 일종의 해킹입니다. 이러한 모든 해킹과 마찬가지로 향후 버전의 데이터베이스에서는 불필요하거나 상황을 악화시킬 수 있습니다. 따라서 작동하더라도 가치가 있는지 결정해야합니다.



0

흠 ...이 하나의 저장 프로 시저에만 초점을 맞추면 캐시 된 실행 계획을 사용하면 현재보고있는 문제가 발생한다는 것에 놀랄 것입니다. 고객과 두 날짜에 대한 매개 변수 집합을 사용하여 저장 프로 시저의 실행 계획을 보도록 요청할 것입니다. customerId와 같이 더 구체적인 색인이 도움이 될지 궁금합니다. 두 날짜 만?


2
왜 놀랍습니까? 매개 변수 스니핑은 이러한 증상에서 상당히 일반적인 문제이며 DBA가이를 문제로 식별 한 것처럼 보입니다.
Martin Smith

@MartinSmith-매개 변수 스니핑에 대해 알고있는 DBA가 재 컴파일 힌트에 대해 알지 못한다는 것에 약간 놀랐습니다.
JNK

@JNK-맞습니다. 그들이 왜 언급하지 않았는지 잘 모르겠습니다.
Martin Smith

0

통계가 누락되어 발생하는 비효율적 인 쿼리 계획처럼 성능이 갑자기 저하됩니다. "오류 및 경고"이벤트 범주가 설정된 SQL Server 프로파일 러를 실행하고 누락 된 통계에 대한 경고가 있는지 확인하십시오.

인덱스가 누락되었거나 SQL Server에서 사용하기에는 인덱스가 너무 조각화되어 인덱스 조각 모음이 필요할 수 있으므로 테이블 스캔에서 I / O가 줄어든다고 생각할 수 있습니다.

@JNK는 저장된 procs에 대해 좋은 점을 제기합니다. 이들은 미리 컴파일되어 쿼리 계획이 저장 프로 시저와 함께 저장됩니다.

WITH RECOMPILE 사용에 반드시 동의하지는 않습니다 됩니다. 그러면 쿼리 계획이 저장되어 재사용되는 이점을 잃게됩니다. 이것이 필요한 경우가 있습니다. 즉, 기본 테이블의 분배 통계가 호출마다 크게 다르지만 일반적으로 테이블의 데이터가 완성되면 테이블 내의 데이터 분배가 최소로 변합니다.

따라서 요약하면 다음과 같습니다.

  1. 누락 된 통계 확인
  2. 인덱스 조각화 확인
  3. 저장된 프로세스 생성 및 사용
  4. proc의 이름을 바꾸십시오. sp_는 내부 시스템 SQL Server 프로세스를 위해 예약 된 접두사 네임 스페이스입니다. 따라서 SQL Server는 항상 해당 저장 프로 시저에 대한 마스터 데이터베이스를 먼저 찾습니다. sp_ 대신 proc usp_의 이름을 바꾸면 성능이 향상되지만이 경우 문제가 의심됩니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.