답변:
몇 가지 이유를 자세히 살펴보고 기능의 일반적인 제한 사항에 대해서도 이야기합니다.
먼저, 누락 된 인덱스 기능의 한계 :
- 인덱스에서 열을 사용할 순서를 지정하지 않습니다.
이 Q & A에서 언급 한 것처럼 SQL Server는 누락 된 인덱스 요청에서 키 열 순서를 어떻게 결정합니까? 인덱스 정의의 열 순서는 Equal vs Inequality 술어와 테이블의 열 서수 위치에 의해 결정됩니다.
선택성에 대한 추측은 없으며 더 나은 주문이 가능합니다. 그것을 알아내는 것이 당신의 일입니다.
특수 인덱스
누락 된 인덱스 요청에는 다음과 같은 '특별한'인덱스도 포함되지 않습니다.
누락 된 인덱스 키 열은 다음과 같은 결과 필터링에 사용되는 열에서 생성됩니다.
누락 된 색인 포함 열은 다음과 같이 쿼리에 필요한 열에서 생성됩니다.
자주 주문하더라도 그룹화하거나 그룹화하는 열이 주요 열로 유용 할 수 있습니다. 이것은 제한 중 하나로 돌아갑니다.
- 인덱싱 구성을 미세 조정하지는 않습니다.
예를 들어 LastAccessDate에 인덱스를 추가하면 정렬 (및 디스크 유출)이되지 않아도이 쿼리는 누락 된 인덱스 요청을 등록하지 않습니다.
SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;
위치에 대한이 그룹화 쿼리도 없습니다.
SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location
그래,하지만 아무것도 아닌 것보다 낫다. 울부 짖는 아기와 같은 누락 된 색인 요청을 생각하십시오. 문제가 있다는 것을 알고 있지만 그 문제가 무엇인지 알아내는 것은 성인의 책임입니다.
긴장을 풀어 라. 우리는 거기에 도착하고있다.
TF 2330 을 사용하면 누락 된 인덱스 요청이 기록되지 않습니다. 이 기능을 활성화했는지 확인하려면 다음을 실행하십시오.
DBCC TRACESTATUS;
인덱스 를 다시 작성 하면 누락 된 인덱스 요청이 지워집니다. 따라서 Hi-Ho-Silver-Away는 모든 인덱스를 재 구축하기 전에 조각화의 두 번째로 몰입 할 때마다 매번 삭제하는 정보에 대해 생각하십시오.
어쨌든 인덱스 조각 모음이 도움이되지 않는 이유 에 대해 생각할 수도 있습니다 . 당신이 사용하지 않는 Columnstore을 .
인덱스를 추가, 제거 또는 비활성화하면 해당 테이블에 대한 누락 된 인덱스 요청이 모두 지워집니다. 동일한 테이블에서 여러 인덱스 변경을 수행하는 경우 변경하기 전에 모두 스크립팅해야합니다.
계획이 간단하고 인덱스 액세스 선택이 분명하고 비용이 충분히 낮 으면 사소한 계획을 얻게됩니다.
이는 효과적으로 옵티마이 저가 결정할 비용 기반 결정이 없음을 의미합니다.
비아 폴 화이트 :
사소한 계획 변경으로 혜택을 얻을 수있는 쿼리 유형에 대한 세부 정보는 일반적으로 조인, 하위 쿼리 및 부등식 술어와 같은 것이 일반적으로 이러한 최적화를 방해합니다.
계획이 사소한 경우 추가 최적화 단계를 탐색하지 않고 누락 된 인덱스를 요청하지 않습니다 .
이 쿼리와 계획 의 차이점을 확인하십시오 .
SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2;
SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2
AND 1 = (SELECT 1);
첫 번째 계획은 사소한 것이며 요청이 표시되지 않습니다. 버그로 인해 누락 된 인덱스가 쿼리 계획에 나타나지 않는 경우가 있습니다. 그러나 일반적으로 누락 된 인덱스 DMV에보다 안정적으로 기록됩니다.
인덱스가 있어도 옵티마이 저가 인덱스를 효율적으로 사용할 수없는 술어는 로그되지 않을 수 있습니다.
일반적으로 SARGable이 아닌 것은 다음과 같습니다.
SELECT *
FROM dbo.Users AS u
WHERE ISNULL(u.Age, 1000) > 1000;
SELECT *
FROM dbo.Users AS u
WHERE DATEDIFF(DAY, u.CreationDate, u.LastAccessDate) > 5000
SELECT *
FROM dbo.Users AS u
WHERE u.UpVotes + u.DownVotes > 10000000
DECLARE @ThisWillHappenWithStoredProcedureParametersToo NVARCHAR(40) = N'Eggs McLaren'
SELECT *
FROM dbo.Users AS u
WHERE u.DisplayName LIKE @ThisWillHappenWithStoredProcedureParametersToo
OR @ThisWillHappenWithStoredProcedureParametersToo IS NULL;
이러한 쿼리 중 누락 된 인덱스 요청은 등록하지 않습니다. 이에 대한 자세한 내용은 다음 링크를 확인하십시오.
이 색인을 보자 :
CREATE INDEX ix_whatever ON dbo.Posts(CreationDate, Score) INCLUDE(OwnerUserId);
이 쿼리에는 문제가 없습니다.
SELECT p.OwnerUserId, p.Score
FROM dbo.Posts AS p
WHERE p.CreationDate >= '20070101'
AND p.CreationDate < '20181231'
AND p.Score >= 25000
AND 1 = (SELECT 1)
ORDER BY p.Score DESC;
계획은 간단합니다.
그러나 주요 키 열은 덜 선택적인 술어를위한 것이기 때문에 다음과 같이 더 많은 작업을 수행하게됩니다.
'게시물'표. 스캔 카운트 13, 논리적 읽기 136890
인덱스 키 열 순서를 변경하면 작업이 훨씬 줄어 듭니다.
CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);
그리고 훨씬 적은 읽기 :
'게시물'표. 스캔 횟수 1, 논리적 읽기 5
경우에 따라 SQL Server는 인덱스 스풀을 통해 즉석에서 인덱스를 만들도록 선택합니다. 인덱스 스풀이 있으면 누락 된 인덱스 요청이 없습니다. 인덱스를 직접 추가하는 것은 좋은 생각이지만 SQL Server를 사용하여 계산할 수는 없습니다.