2009-12-20 3 views
3

이 위치에서 시작할 위치가 확실하지 않습니다. 쿼리 최적화 프로그램을 속일 수 있는지 또는 내재적인지 여부가 확실하지 않은지 확실하지 않습니다. null이 관련되어있을 때 인덱스가 작동하는 방식. 당신이에 저장된 프로 시저를 할 때SQL Server 쿼리 최적화 : Where (Col = @ Col 또는 @ Col = Null)

declare procedure SomeProc 
    @ID int = null 
as 
    select 
    st.ID,st.Col1,st.Col2 
    from 
    SomeTable st 
    where 
    (st.ID = @ID or @ID is null) --works, but very slow (relatively) 

매우 간단한 테스트 케이스에 유용 물론,하지만 다른 시나리오에서 유용하지 않음 : 나는 다음 한

한 코딩 규칙은 같은 저장 프로 시저를 코딩하는 것입니다 몇 가지 기준을 충족하는 전체 테이블 또는 행에서 작동합니다. 내가 가진 where 절을 대체하는 것보다 대략 3-5x 느린 ... 더 큰 테이블을 사용하는 경우 그러나, 아주 느린 : 나는 심지어와 널을 대체한다는 사실에 의해 더욱 의아해 해요

where 
    st.ID = @ID --3-5x faster than first example 

-1 저와 거의 동일한 속도를 제공하는 "고정"WHERE 절 위 : 분명히

declare procedure SomeProc 
    @ID int = -1 
as 
    select 
    st.ID,st.Col1,st.Col2 
    from 
    SomeTable st 
    where 
    (st.ID = @ID or @ID=-1) --much better... but why? 

그것은 정확히, 엉뚱한 일을하지만, 왜 널? 대답은 실행 계획을 검토하는 것으로부터 분명하지 않습니다. 이것은 내가 수년 동안 다양한 데이터베이스, 테이블 및 SQL Server 버전에서 눈치 챈 것입니다. 따라서 현재 환경의 버클이라고 생각하지 않습니다. 기본 매개 변수 값을 null에서 -1로 전환하여 문제를 해결했습니다. 내 질문은 입니다 왜이 작동합니다.

노트는

  1. SomeTable.ID는
  2. 가 그것은 그것을 가치가 무엇이든 들어 문제 Parameter Sniffing (or Spoofing) in SQL Server 스니핑 매개 변수를 관련이있을 수 있습니다 (또는, 사실 일 수 있음)
  3. , 내가 봤는데 색인 "exec SomeProc"로 거의 독점적으로 테스트합니다. proc를 편집/재 컴파일 한 후, 즉 의 선택적 매개 변수가 생략되었습니다.

답변

6

당신은 가장 가능성,

  1. 매개 변수 스니핑
  2. 또는 계획을 보지 않고

하지만를 사용하는 것이 운영자 아니며, 이러한 교육을 추측을 문제의 조합이 .

매개 변수의 기본 "NULL"의

... 스니핑. 다른 기본값 (-1 또는 기본값 없음)으로 시도하십시오.

@ID = -1은 기본값이 NULL이고 매개 변수 스니핑 = 사소한 확인이므로 빠릅니다.

또한 SQL 서버 2008

OR 연산자

몇 가지 아이디어에 OPTIMISE FOR UNKNOWN을 시도 할 수 있습니다 ..열이 널 (NULL)이 아닌 경우

는, 대부분의 경우 옵티마이는 모두 비슷한 방식으로 문

IF @ID IS NULL 
    SELECT ... FROM... 
ELSE 
    SELECT ... FROM... WHERE st.ID 

또는 UNION 경우 사용할 수 있습니다, 또한 조건을

st.ID = ISNULL(@ID, st.ID) 

을 무시합니다.

개인적으로, 나는 대부분의 경우에 매개 변수 (항상) 마스킹 및 ISNULL을 사용하려는 큰 회신

alter procedure SomeProc 
    @ID int = NULL 
AS 
declare @maskID int 
select @maskID = @ID 
... 
+0

감사합니다 (I 먼저 시도 것). 나는 그것이 다른 어떤 것보다 더 중요하다고 생각합니다. 나는 비용이 많이 드는 OR이 얼마나 무지인지를 잘 모르고있었습니다. 결국, 당신의 신호 후, 나는 가독성을 위해 저장된 proc의 맨 위에 SET @ ID = ISNULL (@ ID, -1)을 사용했다. (실제 저장되어있는 proc는 꽤 길고 "내부"의 기본 설정을 묻지 않기를 원했습니다.) 다시 한번 감사드립니다. –

관련 문제