SQL Server 2012에서 빈 결과 집합으로 쿼리 오류가 발생하는 이유는 무엇입니까?


31

MS SQL Server 2012에서 다음 쿼리를 실행할 때 두 번째 쿼리는 실패하지만 첫 번째 쿼리는 실패하지 않습니다. 또한 where 절없이 실행하면 두 쿼리가 모두 실패합니다. 둘 다 빈 결과 집합을 가져야하는데 왜 실패할까요? 모든 도움 / 통찰력을 부탁드립니다.

create table #temp
(id     int primary key)

create table #temp2
(id     int)

select 1/0
from #temp
where id = 1

select 1/0
from #temp2
where id = 1

답변:


39

실행 계획을 처음 살펴보면 표현식 1/0이 Compute Scalar 연산자에 정의되어 있음을 보여줍니다 .

그래픽 계획

이제 실행 계획이 맨 왼쪽에서 실행되기 시작하지만 자식 반복자 에서 반복적으로 호출 Open하고 GetRow메서드를 반환하여 결과를 반환하지만 SQL Server 2005 이상에는 계산 이 종종 계산 스칼라에 의해서만 정의 되고 그 이후까지 평가가 지연 되는 최적화가 포함되어 있습니다. 작업 결과가 필요합니다 .

SET STATISTICS XML로 생성 된 실행 계획에 나타나는 Compute Scalar 연산자에는 RunTimeInformation 요소가 포함되어 있지 않을 수 있습니다.  그래픽 실행 계획에서 SQL Server Management Studio에서 실제 실행 계획 포함 옵션을 선택하면 실제 행, 실제 리 바인드 및 실제 되감기가 속성 창에 없을 수 있습니다.  이러한 상황이 발생하면 이러한 연산자가 컴파일 된 쿼리 계획에 사용되었지만 런타임 쿼리 계획의 다른 연산자가 해당 작업을 수행했음을 의미합니다.  또한 SET STATISTICS PROFILE에 의해 생성 된 실행 계획 출력의 실행 횟수는 SET STATISTICS XML에 의해 생성 된 실행 계획의 리 바인드 및 되감기의 합과 같습니다.  보낸 사람 : MSDN Books Online

이 경우 표현식 결과 는 클라이언트로 리턴하기 위해 행을 어셈블 할 때만 필요합니다 (녹색 SELECT아이콘 에서 발생한다고 생각할 수 있음 ). 이 논리에 따르면 지연된 평가는 계획이 리턴 행을 생성하지 않으므로 표현식이 평가되지 않음을 의미합니다. 포인트를 조금만 사용하기 위해 Clustered Index Seek 또는 Table Scan이 행을 반환하지 않으므로 클라이언트로 반환하기 위해 어셈블 할 행이 없습니다.

그러나 일부 표현은 다음과 같이 확인 할 수있다 별도의 최적화가 런타임 상수쿼리 실행이 시작되기 전에 일단 평가는 . 이 경우 실행 계획 XML (왼쪽의 클러스터 된 인덱스 검색 계획, 오른쪽의 테이블 스캔 계획)에서이 문제가 발생했음을 나타냅니다.

실행 계획 XML

기본 메커니즘 과이 블로그 게시물에서 성능 영향을 줄 수있는 방법에 대해 더 많이 썼습니다 . 여기에 제공된 정보를 사용하여 첫 번째 쿼리를 수정하여 실행이 시작되기 전에 두 표현식을 모두 평가하고 캐시 할 수 있습니다.

select 1/0 * CONVERT(integer, @@DBTS)
from #temp
where id = 1

select 1/0
from #temp2
where id = 1

이제 첫 번째 계획에는 상수 표현식 참조도 포함되어 있으며 두 쿼리 모두 오류 메시지를 생성합니다. 첫 번째 쿼리의 XML에는 다음이 포함됩니다.

상수 표현

추가 정보 : 계산 스칼라, 식 및 성능


21

나는 지능적으로 추측 할 것입니다 (그리고 그 과정에서 아마도 실제로 자세한 답변을 줄 수있는 SQL Server 전문가를 끌어 들일 것입니다).

첫 번째 쿼리는 다음과 같이 실행에 접근합니다.

  1. 기본 키 인덱스 스캔
  2. 쿼리에 필요한 데이터 테이블에서 값을 찾으십시오.

where기본 키에 절이 있으므로이 경로를 선택합니다 . 두 번째 단계에 도달하지 않으므로 쿼리가 실패하지 않습니다.

두 번째는 실행할 기본 키가 없으므로 다음과 같이 쿼리에 접근합니다.

  1. 데이터의 전체 테이블 스캔을 수행하고 필요한 값을 검색하십시오.

이러한 값 중 하나가 1/0문제의 원인입니다.

쿼리를 최적화하는 SQL Server의 예입니다. 대부분의 경우 이것은 좋은 것입니다. SQL Server는에서 조건을 select테이블 스캔 작업으로 이동 합니다. 이것은 종종 쿼리 평가 단계를 저장합니다.

그러나이 최적화는 완화되지 않은 것이 아닙니다. 실제로이 절은 이전에 평가 된다는 SQL Server 설명서 자체 를 위반 한 것으로 보입니다 . 글쎄, 그들은 이것이 무엇을 의미하는지에 대한 설득력있는 설명을 가지고있을 것입니다. 그러나 대부분의 인간에게 논리적으로 이전을 처리하는 것은 "다른 것들과 함께" " 사용자에게 반환되지 않은 행에서 -clause 오류를 생성하지 않음 "을 의미합니다.whereselectwhereselectselect


1
+1 당신이 옳다면 단서가 없지만 가장 좋은 대답은 유일한 차이점은 기본 키라는 것입니다.

1
@GordonLinoff Paul Randal이 트위터를 통해 답장을 보낸 것을 확인했습니다.
SchmitzIT 2014

4
@Still, 실제 실행 순서는 다르지만 이와 같은 오류 메시지가 발생하지 않아야합니다.
ypercubeᵀᴹ

7
@ypercube Erland Sommarskog 님이 동의 할 것입니다 (연결 항목)
Paul White는 GoFundMonica가 말합니다.

2
포인터 주셔서 감사합니다-로그인하여 요청을 승인했습니다.
Gordon Linoff
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.