2014-12-18 6 views
1

이 동작을 이해하려고합니다. 나의 아래 진술은 완료하는데 거의 30 분이 걸린다. 그러나 매개 변수 @IsGazEnabled (하단의 where 절의 case 문에서) 값을 1로 바꾼다면 1 초가 걸립니다.Where 절에 매개 변수를 추가 할 때의 성능

추정 실행 계획을 보면 매개 변수를 사용할 때 30 분이 소요될 때 비용 (92 %)의 대부분은 중첩 루프 (왼쪽 반치 어셈블리)에 있습니다. 또한 어떤 평행주의가 진행되는 것처럼 보입니다. 나는 단지 실행 계획에 관해 배우는 것 뿐이며 조금 혼란 스럽다. 매개 변수를 사용하지 않을 때 생성되는 계획과 매우 다릅니다.

그렇다면 매개 변수를 갖지 않는 것과 비교할 때 매개 변수를 갖는 것이 실행 계획 및 성능에 어떻게 다른가요?

declare @IsGazEnabled tinyint; 

set @IsGazEnabled = 1; 

select 'CT Ref: ' + accountreference + ' - Not synced due to missing property ref ' + t.PropertyReference 
     from CTaxAccountTemp t 
     where not exists (
      select * 
      from ccaddress a 
      left join w2addresscrossref x on x.UPRN = a.UPRN 
       and x.appcode in (
        select w2source 
        from GazSourceConfig 
        where GazSource in (
         select GazSource 
         from GazSourceConfig 
         where W2Source = 'CTAX' 
        ) 
        union all select 'URB' 
       ) 
      where t.PropertyReference = case @IsGazEnabled when 1 then x.PropertyReference else a.PropertyReference end 
     ); 
+0

매개 변수를 사용하지 않을 때 어떤 종류의 조인이 사용됩니까? 쿼리 끝에 옵션 (MERGE JOIN) 또는 옵션 (HASH JOIN)을 추가하고 도움이되는지 확인할 수 있습니다. –

답변

1

이 쿼리를 다시 생각해보십시오. 시도하고 우선의 NOT EXISTS() 피 -하지만

당신을위한 화의 주요 원인 일반적으로 매우 비효율적 이잖아 등을 (오른쪽에있는 X있는 뭔가 - - 그리고 해당 WHERE x IS NULL 나는 보통 이러한 경우에 LEFT JOIN를 선호) CASE 기반의 WHERE가 될 가능성이 있습니다 - 이제는 내부 쿼리가 EVERY ROW!에 대해 평가됩니다. 두 세트의 실격 판정 기준에 모두 참여하는 것이 더 나을 것 같지만 조인 조건에 매개 변수를 포함하고 왼쪽에 두 개의 합류 기준 중 하나의 오른쪽에 아무것도 없다는 것을 확인하십시오.

Heres how 나는 그것을 다시 쓸 수 있다고 생각 :

declare @IsGazEnabled tinyint; 

set @IsGazEnabled = 1; 

select 'CT Ref: ' + accountreference + ' - Not synced due to missing property ref ' + t.PropertyReference 
    from CTaxAccountTemp t 
    left join ccaddress a2 ON t.PropertyReference = a2.PropertyReference and @IsGazEnabled = 0 
    left join 
     (
      ccaddress a 
      join w2addresscrossref x on x.UPRN = a.UPRN 
       and x.appcode in (  -- could make this a join for efficiency.... 
        select w2source 
        from GazSourceConfig 
        where GazSource in (
         select GazSource 
         from GazSourceConfig 
         where W2Source = 'CTAX' 
        ) 
        union all select 'URB' 
       ) 
     ) ON t.PropertyReference = x.PropertyReference AND and @IsGazEnabled = 1 
    WHERE 
      a2.PropertyReference IS NULL 
      AND x.PropertyReference IS NULL  
    ; 
+0

제임스 감사합니다. 이전에 왼쪽 조인 메서드를 사용했지만, 조인을 사용할 때 잘못된 데이터로 인해 중복 행을 만드는 것을 조심스럽게 생각합니다. 나는 또한 where 절에서 case 문을 사용하는 것이 상당한 타격을 줄 것이라고 생각했으나 그렇게 보이지 않았다. 매개 변수를 추가 할 때만. 따라서 특히 매개 변수가 성능에 영향을 미치는 이유에 대한 나의 호기심. 그러나 나는 당신의 제안을 확실히 받아 들일 것입니다. 건배. – ScubaManDan

+0

@ScubaManDan -'CASE 1 = 1'은 아마도 최적화 된 상태가 될 것입니다 - 따라서 왜 매개 변수가 존재할 때만 히트를 일으키는 지 이유가 있습니다.왼쪽 join 메쏘드는 오른쪽에 중복 된 데이터가있을 때'NOT EXISTS'를 체크하는 것으로 괜찮습니다. (생각해보십시오.)'EXISTS'의 대체물이 아닙니다. 물론 –

+0

입니다. 나는 그것을 사용하지 않았을 때 그것에 대해 생각조차하지 않았습니다. 건배. – ScubaManDan

2

SQL Server (쿼리 최적화 프로그램)가 초기 실행 계획을 만들 때 제공된 매개 변수의 값을 사용하기 때문에 이러한 문제가 발생할 수 있습니다. 일부 테이블의 값이 균등하게 분산되지 않은 경우 생성 된 계획은 매개 변수의 특정 값에 대해서는 실제로 잘 작동하지만 다른 매개 변수에는 실제로 제대로 작동하지 않을 수 있습니다. 일반적으로 매개 변수 스니핑이라고합니다. 각각의 실행 (WITH RECOMPILE) 전에 쿼리 힌트 (OPTIMIZE FOR X) 또는 저장 프로 시저를 다시 컴파일하여이 문제를 해결할 수 있습니다. 두 옵션 모두 부작용이 있으므로 구현하기 전에이 옵션을 철저히 읽어야합니다.

브렌트 오자르 (Brent Ozar)의 사이트에서 자세한 내용을 보려면 herehere을 참조하십시오.

+0

또한 중첩 된 (중첩 된 하위 쿼리))) 대신 조인을 사용하도록 쿼리를 다시 작성하는 것이 좋습니다. 이렇게하면 문제가 모두 해결 될 수 있습니다. –

+0

데이브 감사합니다. 나는 Parameter Sniffing에 대해서 읽고 있었다. 프로 시저에만 적용했을 수도 있습니다. 나는 그 기사들을 살펴볼 것입니다. – ScubaManDan

+0

지금까지 매개 변수 스니핑에 대한 모든 내용은 저장 프로 시저에서 발생하는 것을 나타냅니다. 이것은 SSMS에서 직접 실행되는 단순한 명령문입니다. :/ – ScubaManDan