2013-04-16 1 views
4

IN 절이있는 sql 쿼리가 있습니다. 쿼리 계획 캐싱을 향상시키기 위해 테이블 ​​반환 매개 변수를 사용하기로 결정했습니다. 다음은 샘플 WHERE ID IN (SELECT ID FROM @P1)입니다. P1 @ 는 다음과 같은 유형의 변수입니다 :in 절에 대한 테이블 반환 매개 변수가 더 느립니다.

CREATE TYPE [dbo].[Ids] AS TABLE(
    [ID] [int] NOT NULL, 
    PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (IGNORE_DUP_KEY = OFF) 
) 

하지만 일부 쿼리가 느려질 것을 알 수 있습니다. 내 DB에 2.1 초에 수행

select * from SomeTable s where ((s.SomeForeignId in (select id from @p1)) or s.SomeForeignId is null) 

: 다음은 쿼리 예입니다.

그리고 된 쿼리 : 1.8 초에

select * from SomeTable s where ((s.SomeForeignId in (1,2,3.....)) or s.SomeForeignId is null) 

수행한다.

쿼리 계획의 차이점을 확인했습니다. 첫 번째 쿼리의 계획은 두 부분으로 구성됩니다 (하나는 null 검사, 하나는 in 절). 그런 다음 연결이됩니다. 두 번째 계획은 단지 색인 찾기 일뿐입니다.

성능 향상을 위해 매개 변수가있는 쿼리를 향상시킬 수있는 방법이 있습니까?

P. 이 샘플은 증류 된 쿼리 일 뿐이므로이 in (select id from @p1) 부분에 잘못된 것이 있는지 알고 싶습니다.

+0

ofcourse ... 선택 진술을 실행하는 서버의 시간이 단축됩니다 –

+0

인덱스, 테이블의 행 수 및 전달할 값의 수를 포함하여'SomeTable'의 테이블 구조를 표시 할 수 있습니까? '@ p1'? 또한 SELECT *를 사용하면서 두 번째 계획에서 인덱스 찾기를 얻는 방법을 명확히 할 수 있습니까? 실제 실행 계획을 어딘가에 게시 할 수 있습니까? –

+0

이것은 샘플 쿼리 일뿐입니다. 표는 1 백만 mln 개의 레코드를 포함하고 @ p1은 약 20 개의 레코드를 포함하고 쿼리 결과는 약 50,000 개의 레코드를 포함합니다. 나는 그 "in (select id from @ p1)"이 절의 매개 변수화에 올바른 방법인지 확인하고 싶습니다. – struhtanov

답변

4

제안의 몇 :

  1. Don't use SELECT * - just list the columns you actually need.
  2. Use the schema prefix always.
  3. 사용 EXISTS (구 캔 단락 이후)보다는 IN :

    SELECT cols FROM dbo.SomeTable AS s 
        WHERE EXISTS (SELECT 1 FROM @p1 WHERE ID = s.SomeForeignId) 
        OR SomeForeignId IS NULL; 
    
  4. 위의 여전히 (본질적으로 UNION 의미)를 연결 끝낼 수 있지만, 당신이 당신의 자신의를 작성하려고 할 수 있습니다 저를 괴롭히는 무슨

    SELECT cols FROM dbo.SomeTable AS s 
        WHERE EXISTS (SELECT 1 FROM @p1 WHERE ID = s.SomeForeignId) 
    UNION ALL 
    SELECT cols FROM dbo.SomeTable 
        WHERE SomeForeignId IS NULL; 
    

t은 다음과 같습니다 UNION ALLOR을 피하기 위해 기존 변형 중 하나라도 거의 2 초가 걸립니다. SomeTable.SomeForeignId에는 외래 키 제약 조건이 아닌 실제 비 클러스터형 인덱스가 있습니다. 귀하의 질문에 귀하가 추구하는 색인임을 분명하지 않습니다.

+0

나는 샘플 쿼리를 게시했습니다. 내 프로덕션 쿼리는 select *를 사용하지 않으며 계획에 사용되는 외래 키에 대한 인덱스를 가지고 있습니다. 조언 3은 도움이되지 않습니다. 시간은 같습니다. 조언 4는 "(1,2,3)"과 같은 시간을줍니다.그러나 제 제작 쿼리가 너무 커서 파티션을 포함하고 있기 때문에 통합으로 이동하고 싶지 않습니다. 나는 "s.SomeForeignId in (@p1에서 select id)"부분을 다시 작성하는 또 다른 빠른 방법이있을 것이라고 생각했습니다. (이 선택 부분은 쿼리 계획이 여러 번 실행된다고 말하면서 불편 함을 느낍니다.) 다른 제안 사항이 없으면 이것을 답으로 표시하겠습니다. 감사합니다! – struhtanov

+1

# 3은 대개 나를 도와줍니다. 실제로 우리 중 일부는 프로덕션 코드에 IN 절이 없다는 내부 "칙령"을 발행했습니다 (귀하가 더 잘 작동한다고 증명할 수있는 경우 제외). Upvote. – granadaCoder

관련 문제