SQL Server는 술어의 상관 관계를 어떻게 알 수 있습니까?


15

카디널리티 추정이 좋지 않은 (간단한 인덱싱, 최신 통계 등) SQL 쿼리를 진단하는 동안 쿼리 계획이 좋지 않은 경우 관련 KB 문서를 찾았습니다. FIX : 쿼리 실행시 성능 저하 SQL Server 2008 또는 SQL Server 2008 R2 또는 SQL Server 2012의 상관 AND 술어를 포함합니다.

KB 기사에서 "상관 된"(예 : 술어 # 2 및 술어 # 1)이 주로 같은 행을 대상으로하는 것이 무엇인지 추측 할 수 있습니다.

그러나 SQL Server가 이러한 상관 관계에 대해 어떻게 알고 있는지 모르겠습니다. 테이블에 두 술어의 열이 포함 된 다중 열 인덱스가 필요합니까? SQL은 통계를 사용하여 한 열의 값이 다른 열의 상관 관계를 확인합니까? 아니면 다른 방법이 사용됩니까?

나는 두 가지 이유로 이것을 요구하고 있습니다 :

  1. 이 핫픽스를 사용하여 개선 할 수있는 테이블 및 쿼리를 확인하는 방법
  2. # 1에 영향을주기 위해 인덱싱, 통계 등에서해야 할 일

답변:


20

아래에 표시된 간단한 AdventureWorks 쿼리 및 실행 계획을 고려하십시오 . 쿼리에에 연결된 조건자가 포함되어 있습니다 AND. 최적화 프로그램의 카디널리티 추정치는 41,211 행입니다.

-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

기본 실행 계획

기본 통계 사용

단일 열 통계 만 제공되는 경우 옵티마이 저는 각 술어에 대한 카디널리티를 개별적으로 추정하고 결과 선택성을 곱하여이 추정값을 생성합니다. 이 휴리스틱은 술어가 완전히 독립적이라고 가정합니다.

쿼리를 두 부분으로 나누면 계산을보다 쉽게 ​​볼 수 있습니다.

-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336;

트랜잭션 기록 테이블에는 총 113,443 개의 행이 포함되므로 68,336.4 추정치는 이 술어에 대한 선택도 68336.4 / 113443 = 0.60238533 을 나타냅니다 . 이 추정치는 다음에 대한 히스토그램 정보를 사용하여 얻습니다.TransactionID 열에 와 쿼리에 지정된 상수 값 .

-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

이 술어의 추정 선택성은 68413.0 / 113443 = 0.60306056 입니다. 다시, 술어의 상수 값과 TransactionDate통계 오브젝트 의 히스토그램에서 계산됩니다 .

술어가 완전히 독립적이라고 가정하면 두 술어의 선택성을 함께 곱하여 추정 할 수 있습니다. 최종 카디널리티 추정치는 결과 선택도에 기본 테이블의 113,443 행을 곱하여 구합니다.

0.60238533 * 0.60306056 * 113443 = 41210.987

반올림 후 이것은 원래 쿼리에서 볼 수있는 41,211의 추정치입니다 (최적화 프로그램은 내부적으로 부동 소수점 연산을 사용합니다).

큰 견적이 아닙니다

TransactionIDTransactionDate열 (일정하게 증가 키와 날짜 열 수시로로) 설정에서는 AdventureWorks 데이터에 밀접한 상관 관계가있다. 이 상관 관계는 독립 가정이 위반되었음을 의미합니다. 결과적으로 사후 실행 쿼리 계획은 추정 된 41,211이 아니라 68,095 개의 행을 표시합니다.

사후 계획

추적 플래그 4137

이 추적 플래그를 사용하면 술어를 결합하는 데 사용되는 휴리스틱이 변경됩니다. 완전한 독립성을 가정하는 대신, 옵티마이 저는 두 술어의 선택성이 상호 연관 될 수있을만큼 충분히 가깝다고 간주합니다.

-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);

TransactionID술어 만 68,336.4 행을 추정 하고 술어 만 68,413 행을 추정했음을 상기하십시오 TransactionDate. 옵티마이 저는 선택성을 곱하기보다는이 두 추정치 중 더 낮은 값을 선택했습니다.

물론 이것은 다른 휴리스틱이지만 상관 AND술어가있는 쿼리의 추정치를 향상시키는 데 도움이 될 수 있습니다 . 각 술어는 가능한 상관 관계가있는 것으로 간주되며 많은 AND절이 관련 될 때 다른 조정이 있지만이 예는 그 기초를 보여줍니다.

여러 열 통계

이는 상관 관계가있는 쿼리에 도움이 될 수 있지만 히스토그램 정보는 여전히 통계의 주요 열에 만 기반합니다. 따라서 다음 후보 다중 열 통계는 중요한 방식이 다릅니다.

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
    (TransactionID, TransactionDate);

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
    (TransactionDate, TransactionID);

그중 하나만 취하면 추가 정보 만 '모든'밀도의 추가 수준이라는 것을 알 수 있습니다. 히스토그램에는 여전히 TransactionDate열에 대한 자세한 정보 만 포함 됩니다.

DBCC SHOW_STATISTICS
    (
        'Production.TransactionHistory', 
        'stats Production.TransactionHistory TransactionDate TransactionID'
    );

다중 열 통계

이러한 다중 열 통계를 사용하면 ...

SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

... 실행 계획은 단일 열 통계 만 사용 가능한 경우 와 정확히 동일한 추정치를 보여줍니다 .

여러 열 통계 계획

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.