2010-03-02 2 views
2

우리는 150-200 개의 저장된 procs가있는 SQL Server DB를 가지고 있으며, 모두 sys.dm_exec_query_plan에서 볼 수있는 쿼리 계획을 생성합니다. http://msdn.microsoft.com/en-us/library/ms189747.aspx에 따르면 다음과 같은 조건에서SQL Server 2005의 프로 시저에 대한 쿼리 계획이 없습니다.

, 어떤 실행 계획 출력은 sys.dm_exec_query_plan에 대한 반환 된 테이블의 query_plan 열에 반환되지 않습니다 :

이 plan_handle을 사용하여 지정된 쿼리 계획이
  • 경우 계획 캐시에서 제거 된 경우, 리턴 된 테이블의 query_plan 컬럼은 널입니다. 예를 들어 계획 핸들을 캡처 한 시간과 sys.dm_exec_query_plan과 함께 사용한 시간 사이에 지연이 있으면이 조건이 발생할 수 있습니다.
  • 대량 트랜잭션 문이나 크기가 8KB보다 큰 문자열 리터럴을 포함하는 문과 같이 일부 Transact-SQL 문은 캐시되지 않습니다. 이러한 문에 대한 XML Showplans는 캐시에 존재하지 않기 때문에 일괄 처리가 현재 실행 중이 아니면 sys.dm_exec_query_plan을 사용하여 검색 할 수 없습니다.
  • EXEC (문자열)를 사용하여 Transact-SQL 일괄 처리 또는 저장 프로 시저에 사용자 정의 함수 또는 동적 SQL 호출에 대한 호출이 포함 된 경우 사용자 정의 함수에 대해 컴파일 된 XML 실행 계획이 포함되지 않습니다. 일괄 처리 또는 저장 프로 시저에 대해 sys.dm_exec_query_plan에 의해 반환 된 테이블 대신 사용자 정의 함수에 해당하는 계획 핸들에 대해 sys.dm_exec_query_plan을 별도로 호출해야합니다.

그리고 나중에 ..

때문에, sys.dm_exec_query_plan 충족하거나 중첩 된 128 개 수준을 초과하는 쿼리 계획을 반환 할 수 xml 데이터 형식에서 허용 중첩 수준의 수의 제한 사항 집단.

본인은이 절차에 해당하지 않는다고 확신합니다. 결과에는 쿼리 계획이 없으므로 아무 타이밍이 적용되지 않으므로 1이 적용되지 않습니다. 긴 문자열 리터럴이나 대량 작업이 없으므로 2가 적용되지 않습니다. 사용자 정의 함수 나 동적 SQL이 없으므로 3이 적용되지 않습니다. 그리고 둥지가 거의 없으므로 마지막은 적용되지 않습니다. 사실, 이것은 매우 단순한 proc이며, 나는 (무고한 사람들을 보호하기 위해 테이블 ​​이름을 변경하여) 전체를 포함하고 있습니다. 매개 변수 스니핑 헛소리는 문제를 후태합니다. 쿼리에서 매개 변수를 직접 사용하더라도 여전히 발생합니다. 왜 내가이 proc에 대한 볼 수있는 쿼리 계획이 없는지에 대한 아이디어?

ALTER PROCEDURE [dbo].[spGetThreadComments] 
    @threadId int, 
    @stateCutoff int = 80, 
    @origin varchar(255) = null, 
    @includeComments bit = 1, 
    @count int = 100000 
AS 

if (@count is null) 
begin 
    select @count = 100000 
end 

-- copy parameters to local variables to avoid parameter sniffing 
declare @threadIdL int, @stateCutoffL int, @originL varchar(255), @includeCommentsL bit, @countL int 
select @threadIdL = @threadId, @stateCutoffL = @stateCutoff, @originL = @origin, @includeCommentsL = @includeComments, @countL = @count 

set rowcount @countL 

if (@originL = 'Foo') 
begin 
    select * from FooComments (nolock) where threadId = @threadId and statusCode <= @stateCutoff 
    order by isnull(parentCommentId, commentId), dateCreated 
end 
else 
begin  
    if (@includeCommentsL = 1) 
    begin 
     select * from Comments (nolock) 
      where threadId = @threadIdL and statusCode <= @stateCutoffL 
      order by isnull(parentCommentId, commentId), dateCreated 
    end 
    else 
    begin 
     select userId, commentId from Comments (nolock) 
      where threadId = @threadIdL and statusCode <= @stateCutoffL 
      order by isnull(parentCommentId, commentId), dateCreated 
    end 
end 
+0

3 가지 쿼리 각각에 대한 쿼리 계획을 얻을 수 있습니까? 이 "테이블"은 실제로 함수를 호출 할 수있는 뷰입니까? –

+0

안녕 데이비드. dm_exec_query_stats를 통해 쿼리 계획을 제공하지 않는 plan_handle이 실제로 작업을 수행하고 있음을 확인할 수 있으므로 운영 계획보다는 일부 우산 계획 만보고있는 것 같지 않습니다. – sidereal

+0

와우. 다비드에게 전화하는 것이 좋다. 두 테이블 모두 이론적으로 테이블 일 뿐이지 만 그 중 하나는 실제로 존재하지 않는 테이블입니다. FooComment는 어딘가에서 삭제되었습니다. 그 지점은 분명히 사용되지 않기 때문에 런타임 문제는 발생하지 않았지만 테이블 부족으로 인해 쿼리 계획이 생성되거나 올바르게 표시되지 않는 것처럼 보입니다. 당신이 대답으로 그것을 쓰고 싶다면, 나는 당신에게 신용을 줄 것이다. – sidereal

답변

2

흠의 자신의 자신의 개인 버전을 얻을 것입니다. 그들은 전망이나 다른 것일 수 있습니다.

+0

또는 존재하지 않습니다! 감사합니다 – sidereal

+0

저희 가게는 하나의 데이터베이스에서 다른 데이터베이스로 데이터베이스 구조를 복사 할 때 존재하지 않는 많은 객체가 있습니다. 결국 우리는 빠진 의존성을 탐지하는 도구를 얻었습니다. –

+0

SQL에서 실제로 그 코드 분기를 실행할 때까지 아무 것도 그것에 대해 불평하지 않는 것은 이상한 일입니다. 어딘가에서 경고할만한 가치가있는 것처럼 보입니다. – sidereal

0

시도 dbo. 퍼팅이든 스키마 테이블 이름을 모두의 앞에 한 다음 다시 확인. 기사에서

http://www.sommarskog.se/dyn-search-2005.html

인용 :

은이 문서를 참조하십시오 당신이 볼 수 있듯이

, 나는 두 부분으로 표기 모든 테이블 를 참조하십시오. 즉, 나는 또한 스키마를 지정합니다 (SQL에서 7/2000의 말장난은 일반적으로 소유자로 라고합니다).나는 스키마를 떠날 경우), 각 사용자는 아마도 테이블이 정말 테이블이 아닌 쿼리 계획

+0

안녕하세요. 좋은 연습처럼 보입니다. (실제로 SQL Trace가 실행될 때 제대로 실행되는 쿼리 성능이 좋지 않습니다. 각 쿼리가 서로 다른 쿼리 계획을 얻는 경우). 그러나이 경우 우리는 모든 procs의 정규화 된 이름을 제외하고 쿼리 계획이 부족합니다. – sidereal

관련 문제