왜 IF EXISTS
그렇게 오래 걸리고 더 많은 읽기를 할 수 있을지 알고 있습니까? 또한 select 문을 변경하고 SELECT TOP 1 [dlc].[id]
2 분 후에 죽였습니다.
이 관련 질문에 대한 답변에서 설명했듯이 :
TOP은 실행 계획에 어떤 영향을 미칩니 까?
를 사용 EXISTS
하면 행 목표가 도입됩니다. 여기서 옵티마이 저는 첫 번째 행을 빠르게 찾기위한 실행 계획을 생성합니다. 이를 수행 할 때 데이터가 고르게 분포되어 있다고 가정합니다. 예를 들어 통계에 100,000 개의 행에 100 개의 예상 일치 항목이있는 경우 첫 번째 일치 항목을 찾으려면 1,000 개의 행만 읽어야한다고 가정합니다.
이 가정에 결함이있는 경우 예상 실행 시간보다 길어집니다. 예를 들어, SQL Server가 검색에서 가장 늦은 첫 번째 일치 값을 찾는 액세스 방법 (예 : 정렬되지 않은 스캔)을 선택하면 거의 완전한 스캔이 발생할 수 있습니다. 반면, 처음 몇 행에서 일치하는 행이 발견되면 성능이 매우 좋아집니다. 일관성없는 성능-행 목표의 근본적인 위험입니다.
임시 수정으로 count (*)를 수행하고 해당 값을 변수에 할당하도록 변경했습니다.
일반적으로 행 목표가 지정되지 않도록 쿼리를 재구성 할 수 있습니다. 행 목표가 없으면 일치하는 첫 번째 행이 발견 될 때 (정확하게 작성된 경우) 쿼리가 계속 종료 될 수 있지만 실행 계획 전략이 다를 수 있습니다 (바람직하게는 더 효과적 임). 분명히 count (*)는 모든 행을 읽어야하므로 완벽한 대안이 아닙니다.
SQL Server 2008 R2 이상을 실행하는 경우 일반적으로 문서화되고 지원되는 추적 플래그 4138 을 사용하여 행 목표없이 실행 계획을 얻을 수 있습니다. 계획 안내서와 함께 사용하지 않는 한이 플래그는 지원되는 hint를 사용하여 지정할 수도 OPTION (QUERYTRACEON 4138)
있지만 런타임 sysadmin 권한 이 필요합니다 .
운수 나쁘게
위의 어느 것도 IF EXISTS
조건문 과 함께 작동하지 않습니다. 일반 DML에만 적용됩니다. 그것은 것입니다 대체 작업 SELECT TOP (1)
이 시도 배합. COUNT(*)
앞에서 언급 한 것처럼 모든 정규화 된 행을 계산해야하는를 사용 하는 것보다 낫습니다 .
즉, 검색을 조기에 종료하면서 행 목표를 피하거나 제어 할 수있는이 요구 사항을 표현하는 방법에는 여러 가지가 있습니다. 마지막 예 :
DECLARE @Exists bit;
SELECT @Exists =
CASE
WHEN EXISTS
(
SELECT [dlc].[ID]
FROM TableDLC [dlc]
JOIN TableD [d]
ON [d].[ID] = [dlc].[ID]
JOIN TableC [c]
ON [c].[ID] = [d].[ID2]
WHERE [c].[Name] <> [dlc].[Name]
)
THEN CONVERT(bit, 1)
ELSE CONVERT(bit, 0)
END
OPTION (QUERYTRACEON 4138);
IF @Exists = 1
BEGIN
...
END;
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
입니다.