11

전체 텍스트 색인을 사용하여 제품 (250,000 행)을 검색하는 저장된 proc가 있습니다.왜이 두 쿼리의 성능이 다릅니 까?

저장된 proc는 전체 텍스트 검색 조건 인 매개 변수를 사용합니다. 이 매개 변수는 null 일 수 있으므로 null 확인을 추가하면 쿼리가 갑자기 순서가 느리게 실행되기 시작했습니다.

쿼리 # 1 Execution plant #1

쿼리 # 2 Execution plant #2

내가 실행 계획에 매우 익숙하지 않은임을 인정해야합니다

-- This is normally a parameter of my stored proc 
DECLARE @Filter VARCHAR(100) 
SET @Filter = 'FORMSOF(INFLECTIONAL, robe)' 

-- #1 - Runs < 1 sec 
SELECT TOP 100 ID FROM dbo.Products 
WHERE CONTAINS(Name, @Filter) 

-- #2 - Runs in 18 secs 
SELECT TOP 100 ID FROM dbo.Products 
WHERE @Filter IS NULL OR CONTAINS(Name, @Filter) 

다음은 실행 계획이다. 유일한 차이점은 조인이 다르다는 것입니다. 힌트를 추가하려고하지만 내 쿼리에 조인을하지 않으면 어떻게 할 지 모르겠다.

IX_SectionID라는 인덱스가 사용 된 이유는 그것이 ColumnID 만 포함하고 그 열은 어디에도 사용되지 않은 인덱스이기 때문에 이해가되지 않습니다.

답변

8

OR 성능 호감, 그래서 이런 식으로 수행 할 수 있습니다 Dynamic Search Conditions in T-SQL by Erland Sommarskog이 질문 : SQL Server 2008 - Conditional Query이 문서에서

DECLARE @Filter VARCHAR(100) 
SET @Filter = 'FORMSOF(INFLECTIONAL, robe)' 

IF @Filter IS NOT NULL 
BEGIN 
    SELECT TOP 100 ID FROM dbo.Products 
    WHERE CONTAINS(Name, @Filter) 
END 
ELSE 
BEGIN 
    SELECT TOP 100 ID FROM dbo.Products 
END 

봐.

+0

멋진 기사 - OPTION (RECOMPILE)'추가'실제로 2 쿼리의 성능 문제를 (해결하지만 또 다른 문제는'()'인상이 포함되어 있습니다 매개 변수가 NULL이지만 다른 문제 인 경우 오류). –

1

OR 조건을 도입했습니다. 대부분의 경우 명시 적으로 NULL을 확인하고 하나의 쿼리와 메서드를 비교하는 것이 훨씬 빠릅니다.

예를 들어이 시도 :

IF @Filter IS NULL 
BEGIN 
SELECT TOP 100 ID FROM dbo.Products 
END 
ELSE 
BEGIN 
SELECT TOP 100 ID FROM dbo.Products 
WHERE @Filter CONTAINS(Name, @Filter) 
END 
3

첫 번째 쿼리 계획은 간단 같습니다

  1. 전체 텍스트 검색의 다른 열을 조회 CONTAINS(Name, @Filter)
  2. 인덱스 스캔을 해결하기 위해 일치 행
  3. 해시 조인을 사용하여 둘을 결합하십시오.

concatenation operator은 두 레코드 세트의 합집합을 구성합니다. 두 번째 쿼리가하고있는 것처럼 그래서 같습니다

  1. (나중에 다른 열을 조회하는 데 사용) 인덱스 스캔
  2. 일정한 스캔. 난 당신의 쿼리를 매개 변수화되지 않은 것으로 간주하므로 쿼리 계획은 다른 값인 @Filter에 대해 작동하지 않아도됩니다. 올바른 경우, 상수 스캔은 @Filter is not null을 해결합니다.
  3. 전체 텍스트 검색이
  4. 루프에서 빈 세트 CONTAINS(Name, @Filter)
  5. 조합 3의 결과를 해결할 수는

해시 조인 다른 열 조회 1과 4의 결과를 조인 속도를위한 기억을 거래한다. 시스템에 충분한 메모리가 있으면 루프 결합보다 훨씬 빠릅니다. 이것은 10-100x 감속을 쉽게 설명 할 수 있습니다.

한 수정 프로그램은 두 가지 쿼리를 사용하는 것입니다

if @Filter is null 
    SELECT TOP 100 ID FROM dbo.Products 
else 
    SELECT TOP 100 ID FROM dbo.Products WHERE CONTAINS(Name, @Filter) 
+0

흥미 롭습니다 - 두 번째 쿼리에서 해시 조인을 강제 적용 할 수있는 방법이 있습니까? –

+0

예, 내부 해시 조인을 사용하여 다시 작성할 수는 있지만 다소 복잡 할 수 있습니다. Sommarskog 기사의 솔루션 중 하나를 사용하는 것이 좋습니다. – Andomar

관련 문제