Retailer_Relations 테이블에는 다음과 같은 복합 PK 색인과 제안 된 색인이 있습니다.
누락 된 인덱스가 도움이되고 확실히 작동 할 수 있지만 누락 된 인덱스에 너무 많은 시간을 소비하지는 않지만 이러한 힌트는 실제 실행 계획이 아니라 예상 실행 계획에 생성됩니다.
보다 정확하게,이 색인 힌트는 계획에서 운영자가 사용하는 Query Bucks ™ 비용을 절감한다는 전제를 기반으로합니다. 옵티마이 저는 예상 비용을 계산하고 이에 따라 누락 된 인덱스 힌트를 추가합니다.
결과적으로 그들은 매우 틀릴 수 있습니다. 도움이 될지 확실하지 않은 경우 가장 좋은 방법은 전후 상황을 테스트하는 것입니다. SET STATISTICS IO, TIME ON;
조회를 실행하기 전에 명령문을 추가하여이를 수행 할 수
있습니다.
또한 statisticsparser 를 사용하여 이러한 통계를보다 쉽게 읽을 수 있습니다.
인덱스의 열 순서 때문일 수 있습니까?
맞습니다. 누락 된 인덱스를 만들면 쿼리의 선택성이 향상 될 수 있습니다 (예 : 쿼리가 다음과 같은 경우).
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
또는 이와 같이 :
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
그 이유는 두 인덱스 모두 RetailerID를 검색 할 수 있고 그 부분은 변경되지 않기 때문입니다. 그러나 RelationType에 추가 필터 / 순서를 적용하면 어떻게됩니까? 두 번째 키 값이 아닌 세 번째 키 값으로 인해 클러스터형 인덱스의 모든 위치에 적용됩니다. 그리고 우리가 아는 것처럼 NCI의 두 번째 핵심 가치입니다.
좋습니다. 그러나 비 클러스터형 인덱스는 언제 또는 어떻게 쿼리를 개선합니까?
몇 가지 경우가 있습니다.
- relationType이 많은 값을 필터링하면 잔여 I / O가 높아져 비 클러스터형 인덱스가 필요할 수 있습니다 (질의 # 1).
- 두 열의 순서는 (편도) 발생하고 결과 집합이 큽니다 (질의 # 2).
- @AaronBertrand가 언급했듯이 NCI와 비교 한 CI 크기 차이가 상당하면 NCI를 추가하면 혜택을 얻는 쿼리에서 읽는 페이지가 줄어 듭니다.
NCI 사이드 노트
참고로 CI 키 열은 모든 비 클러스터형 인덱스에 자동으로 포함되므로 NCI의 포함 목록에 키 열을 추가 할 필요는 없습니다.
클러스터형 인덱스가 동일하게 유지되는지 확실하지 않고 열이 항상 포함되도록하려는 경우이를 수행 할 수 있습니다.
쿼리 자체와 관련하여 PasteThePlan 을 통해 실행 계획을 추가 한 경우 쿼리 인덱싱 / 개선에 대한 추가 정보를 제공 할 수 있습니다.
테스팅
테이블 만들기 및 일부 행 추가
CREATE TABLE Retailer_Relations (
RetailerID int ,
RelatedRetailerID int ,
RelationType smallint,
CreatedOn datetime,
CONSTRAINT PK_Retailer_Relations
PRIMARY KEY CLUSTERED (
RetailerID ASC,
RelatedRetailerID ASC,
RelationType ASC
) ON [PRIMARY])
DECLARE @I Int = 1
WHILE @I < 1000
BEGIN
INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
VALUES(@I,@I,@I,GETDATE()
)
set @I += 1
END
쿼리 # 1
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
인덱스없이 계획 여기에
검색을하는 동안 RetailerID를 검색합니다. 이후에 RelationType에서 잔여 I / O 술어를 발행합니다.
색인 추가
CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
RetailerID,
RelationType
)
INCLUDE (
RelatedRetailerID
)
잔차 술어가 사라지고 모든 열이 두 술어에서 탐색 술어에서 발생합니다.
실행 계획
두 번째 쿼리에서는 추가 된 인덱스 유용성이 훨씬 더 명확 해집니다.
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
정렬 연산자를 사용하여 인덱스없이 계획하십시오.
인덱스를 사용하여 계획을 세웁니다. 인덱스를 사용하면 정렬 연산자가 제거됩니다.