2010-05-07 3 views
2

마지막 질문 인 Sql Server query performance에 이어 검색 쿼리에서 선택적 매개 변수를 허용하는 나의 방법이 최적이 아니라는 것을 발견하면 누구에게이 방법에 대한 지침이 있습니까?최적의 검색 쿼리

예를 들어 응용 프로그램 테이블, 고객 테이블 및 연락처 정보 테이블이 있고 성, 집 전화, 모바일 및 응용 프로그램 ID 중 일부 또는 전부를 검색 할 수있는 SP를 만들고 싶습니다. 같은 것을 사용할 수 있습니다 다음

select * 
from application a inner join customer c on a.customerid = a.id 
    left join contact hp on (c.id = hp.customerid and hp.contacttype = 'homephone') 
    left join contact mob on (c.id = mob.customerid and mob.contacttype = 'mobile') 
where (a.ID = @ID or @ID is null) 
    and (c.Surname = @Surname or @Surname is null) 
    and (HP.phonenumber = @Homphone or @Homephone is null) 
    and (MOB.phonenumber = @Mobile or @Mobile is null) 

위에서 사용 된 스키마는 진짜이며, 나는 실제 시나리오에서 선택 *를 사용하지 않을 것, 그것이 내가에 관심이 where 절의 건설입니다 더 나은 접근 방식, 동적 SQL 또는 많은 중첩 된 조건에 대한 필요성없이 같은 결과를 얻을 수있는 대안이 있는가? 그렇지 않으면 첫 번째 쿼리 계획 재사용되고, 아무리 매개 변수 - 여기 우리가

OPTION (RECOMPILE)

이 필수입니다 가고,

답변

3

너 그렇게 해. 쿼리의 속도가 느려지더라도 올바른 대답을 반환하는 것 이상으로이 기사를 살펴 보려면 Dynamic Search Conditions in T-SQL by Erland Sommarskog을 참조하십시오. 모든 방법을 다루며 각 방법의 단점과 단점을 매우 자세하게 설명합니다.

검색 열의 최소 및 최대 범위를 결정할 수 있고 검색 열이 NOT NULL 인 경우 (@Search IS NULL OR Col = @ Search), see this area of the above linked article보다 더 잘 수행 할 수 있습니다. 그러나 전체 기사를 읽어야하고, 상황에 따라 다양한 변형이 있으므로, 여러 접근법을 언제 배울 필요가 있습니다. 다른 쿼리가 다른 인덱스를 사용합니다, 귀하의 경우에는 SQL Server 2008 - Conditional Query

+1

+1 : 좋은 참조 문서를! – RedFilter

+0

훌륭한 기사, 동적 SQL이 (sp_executesql을 사용한다고해도) 악의적이지만 실제로는 스스로 연구하지는 못한다는 DBA 몇 명으로부터 들었습니다. 이 접근법을 사용하기 위해 몇 가지 주요 쿼리를 다시 작성하면 상당한 개선이있었습니다. – Macros

1

확인이 방법에 사용되는 15 기준 - 일부의 SP 10이있을 수 있습니다 시합. 죄송합니다. 더 나은 방법은 없습니다.

그 외에도 - 죄송합니다. 동적 SQL은 (IS NULL 대안을 피함으로써)보다 효율적으로 될 수 있지만, 가능하지 않다면 기본적으로 제한됩니다. homePhone를 변수가 null의 경우 기본적으로 HP.phonenumber에 대한 맞추다가없는 동적 SQL로

)

, 방법에는 미묘한 성능에 영향이있는 어떤이에 대한 쿼리 방법 "하나 개의 크기는 모두 맞는"없다
1

:

또한이 다른 최근의 대답을 참조하십시오.

당신은 UNION ALL와 인덱스 필드에 OR를 교체, 사용 및 각 세트에 대한 개별 쿼리를 작성하려는 인덱스의 집합을 정의한다 :

SELECT * 
FROM tables 
WHERE A = @ID 
     AND (c.Surname = @Surname or @Surname IS NULL) 
     AND (HP.phonenumber = @Homphone or @Homephone IS NULL) 
     AND (MOB.phonenumber = @Mobile or @Mobile IS NULL) 
UNION ALL 
SELECT * 
FROM tables 
WHERE @ID IS NULL 
     AND c.Surname = @Surname 
     AND (HP.phonenumber = @Homphone or @Homephone IS NULL) 
     AND (MOB.phonenumber = @Mobile or @Mobile IS NULL) 
UNION ALL 
SELECT * 
FROM tables 
WHERE @ID IS NULL 
     AND @Surname IS NULL 
     AND (HP.phonenumber = @Homphone or @Homephone IS NULL) 
     AND (MOB.phonenumber = @Mobile or @Mobile IS NULL)