답변:
열이에 없지만 절의 WHERE/JOIN/GROUP BY/ORDER BY
열 목록에만있는 경우SELECT
이 INCLUDE
절은 인덱스 트리가 아니라 가장 낮은 / 리프 레벨에서 데이터를 추가합니다. 이것은 트리의 일부가 아니기 때문에 인덱스를 작게 만듭니다.
INCLUDE columns
인덱스의 키 열이 아니므로 순서가 지정되지 않습니다. 이것은 위에서 언급했듯이 술어, 정렬 등에 실제로 유용하지 않음을 의미합니다. 그러나, 그것은 수 있습니다 당신은 키 컬럼에서 몇 행에 잔류 조회가있는 경우 유용합니다 (들)
SELECT
그렇지 않은 경우에는 어떻게해야합니까? \
INCLUDE를 사용하여 비 클러스터형 인덱스의 리프 수준에 하나 이상의 열을 추가합니다. 이렇게하면 쿼리를 "덮을"수 있습니다.
직원 ID, 부서 ID 및 성을 쿼리해야한다고 상상해보십시오.
SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5
비 클러스터형 인덱스 (EmployeeID, DepartmentID)가있는 경우 특정 부서의 직원을 찾으면 실제 열람을 얻기 위해 "책갈피 조회"를 수행해야합니다. . 많은 직원을 찾으면 성능면에서 꽤 비쌀 수 있습니다.
색인에 해당 성을 포함시킨 경우 :
CREATE NONCLUSTERED INDEX NC_EmpDep
ON Employee(EmployeeID, DepartmentID)
INCLUDE (Lastname)
그런 다음 필요한 모든 정보를 비 클러스터형 인덱스의 리프 수준에서 사용할 수 있습니다. 비 클러스터형 인덱스를 찾아 특정 부서의 직원을 찾으면 필요한 모든 정보를 얻을 수 있으며 인덱스에서 찾은 각 직원에 대한 책갈피 조회가 더 이상 필요하지 않습니다.-> 많은 시간을 절약 할 수 있습니다.
분명히 모든 비 클러스터형 인덱스에 모든 열을 포함 할 수는 없습니다. 그러나 "커버"할 하나 또는 두 개의 열만 누락 된 쿼리가있는 경우 (그리고 많이 사용되는) 쿼리를 포함하면 매우 유용 할 수 있습니다. 적절한 비 클러스터형 인덱스로
JOIN
은 쿼리 의 필터에 있어야하며 , INCLUDE
검색하지만 정렬하지 않은 데이터 여야합니다.
이 논의는 중요한 점을 놓치고 경우 : "키가 아닌 - 열"로 포함하는 더 나은 경우 문제는 아니다 인덱스 -columns 또는 포함 -columns.
문제는 인덱스에 실제로 필요하지 않은 열을 포함시키기 위해 include-mechanism을 사용하는 것이 얼마나 비싸 습니까? (일반적으로 where-clauses의 일부는 아니지만 종종 select에 포함됨). 따라서 당신의 딜레마는 항상 :
여기서 : id1, id2 ... idN은 제한에 자주 사용되는 열이고 col1, col2 ... colN은 자주 선택되지만 제한에 사용 되지 않는 열입니다.
(이러한 모든 열을 인덱스 키의 일부로 포함하는 옵션은 항상 바보입니다 (제한에도 사용되지 않는 한). 인덱스를 업데이트하고 정렬해야 할 때에도 인덱스를 업데이트하고 정렬해야하기 때문에 유지 관리 비용이 항상 비쌉니다. "키"는 변경되지 않았습니다).
옵션 1 또는 2를 사용 하시겠습니까?
답변 : 테이블이 거의 업데이트되지 않는 경우 (주로 삽입 / 삭제되는 경우) include 메커니즘을 사용하여 일부 "핫 컬럼"(일부 선택에 사용되지만 제한에 자주 사용 되지 는 않음) 을 포함하는 것이 비교적 저렴합니다. 삽입 / 삭제는 어쨌든 인덱스를 업데이트 / 정렬해야하므로 인덱스를 업데이트하는 동안 몇 개의 추가 열을 저장하는 것과 관련된 추가 오버 헤드가 거의 없습니다. 오버 헤드는 인덱스에 중복 정보를 저장하는 데 사용되는 추가 메모리 및 CPU입니다.
포함 된 열로 추가하려는 열이 자주 업데이트되는 경우 (인덱스 키- 열이 업데이트 되지 않은 경우 ) 또는 열 이 너무 많은 경우 인덱스가 테이블의 복사본에 가까워지는 경우-옵션 1 사용 나는 제안 할 것이다! 또한 특정 include-column을 추가해도 성능 차이가없는 것으로 판명되면 추가하는 아이디어를 건너 뛸 수 있습니다.) 유용한 지 확인하십시오!
키에서 동일한 값 (id1, id2 ... idN) 당 평균 행 수도 중요 할 수 있습니다.
int로서 첨가 - 컬럼 경우 통지 포함 - 인덱스의 -Column가 사용된다 제한 : 같은 색인이 사용될 수만큼 긴 (인덱스 - 대 제한에 기초하여 키 -columns) - 다음 SQL 서버 매칭 인 테이블 자체를 고가로 사용하는 대신 인덱스 (리프 노드 값)에 대한 열 제한.
기본 인덱스 열은 정렬되지만 포함 된 열은 정렬되지 않습니다. 이를 통해 인덱스 유지 관리에 필요한 리소스를 절약하면서도 포함 된 열에 데이터를 제공하여 쿼리를 처리 할 수 있습니다. 따라서 쿼리를 다루려면 검색 기준을 지정하여 행을 인덱스의 정렬 된 열로 찾은 다음 검색되지 않은 데이터가있는 정렬되지 않은 추가 열을 "포함"할 수 있습니다. 인덱스 유지 관리에서 정렬 및 조각화 양을 줄이는 데 도움이됩니다.
그 이유 (지수의 잎 수준에있는 데이터 포함)가 잘 설명되어 있습니다. 이것에 대해 두 가지 동요를하는 이유는 쿼리를 실행할 때 추가 열이 포함되어 있지 않으면 (SQL 2005의 새로운 기능) SQL Server가 추가 열을 가져 오기 위해 클러스터형 인덱스로 이동해야하기 때문입니다 새로운 데이터 페이지가 메모리에로드 될 때 SQL Server 서비스, 디스크 및 메모리 (구체적으로 특정 버퍼)에 더 많은로드를 추가하여 버퍼 캐시에서 더 자주 필요한 다른 데이터를 푸시 할 수 있습니다.
INCLUDE
키 에서 해당 열이 필요하지 않은 경우 키 열보다 선호하는 한 가지 이유 는 문서입니다. 이는 미래에 진화하는 색인을 훨씬 더 쉽게 만듭니다.
귀하의 예를 고려할 때 :
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
쿼리가 다음과 같은 경우 해당 인덱스가 가장 좋습니다.
SELECT col2, col3
FROM MyTable
WHERE col1 = ...
물론 INCLUDE
주요 부분 에 열을 추가하여 이점을 얻을 수 있다면 열을 넣지 마십시오 . 다음 쿼리는 모두 col2
인덱스 키의 열을 선호합니다 .
SELECT col2, col3
FROM MyTable
WHERE col1 = ...
AND col2 = ...
SELECT TOP 1 col2, col3
FROM MyTable
WHERE col1 = ...
ORDER BY col2
의이이 가정 해 봅시다 없는 경우 우리는이 col2
에서 INCLUDE
인덱스의 나무 부분에있는의 단지 어떤 이점이 없기 때문에 절.
몇 년 빨리 감기.
이 쿼리를 조정해야합니다.
SELECT TOP 1 col2
FROM MyTable
WHERE col1 = ...
ORDER BY another_col
해당 쿼리를 최적화하려면 다음 색인이 좋습니다.
CREATE INDEX idx1 ON MyTable (Col1, another_col) INCLUDE (Col2)
해당 테이블에있는 인덱스를 이미 확인한 경우 이전 인덱스가 여전히있을 수 있습니다.
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
지금 당신은 알고 Col2
및 Col3
인덱스 트리의 일부가 아닌 때문에 읽기 인덱스 범위를 좁힐이나 행을 주문하는 데 사용되지 않습니다. another_column
인덱스의 핵심 부분 끝에 추가 하는 것이 오히려 안전합니다 (after col1
). 아무것도 깨뜨릴 위험이 거의 없습니다 :
DROP INDEX idx1 ON MyTable;
CREATE INDEX idx1 ON MyTable (Col1, another_col) INCLUDE (Col2, Col3);
이 지수는 더 커질 위험이 있지만 새로운 지수를 도입하는 것보다 기존 지수를 확장하는 것이 일반적으로 좋습니다.
이없는 인덱스가 있으면 바로 뒤에 INCLUDE
추가하여 어떤 쿼리를 중단할지 알 수 없었습니다 .another_col
Col1
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
과 another_col
사이에 추가하면 어떻게됩니까 ? 다른 쿼리에 어려움이 있습니까?Col1
Col2
테이블에서 열을 가져 오지 않도록 열을 추가하면 다른 열과INCLUDE
키 열의 다른 이점 이 있습니다 . 그러나 설명서 측면이 가장 중요하다고 생각합니다.
질문에 대답하려면 :
INCLUDE 절을 사용하거나 사용하지 않고 포함 인덱스를 작성할지 여부를 결정할 때 어떤 지침을 제안 하시겠습니까?
테이블을 방문하지 않고 인덱스에서 해당 열을 사용할 수 있도록하기 위해 인덱스에 열을 추가하는 경우 해당 열을 INCLUDE
절에 넣으십시오 .
인덱스 키에 열을 추가하면 추가 인덱스 이점을 얻을 수있는 경우 (예 : order by
읽기 인덱스 범위를 좁힐 수 있기 때문에) 키에 추가하십시오.
이에 대한 자세한 내용은 여기를 참조하십시오.
https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes
인덱스 정의에 인라인 된 모든 열의 총 크기에는 제한이 있습니다. 그럼에도 불구하고, 그렇게 넓은 인덱스를 만들 필요는 없었습니다. 나에게 가장 큰 장점은 특정 순서로 정의 할 필요가 없으므로 열을 포함하는 하나의 인덱스로 더 많은 쿼리를 처리 할 수 있다는 것입니다. 는 인덱스 내의 인덱스로 생각하십시오. 한 가지 예는 StoreID (여기서 StoreID는 선택성이 낮으며 각 상점이 많은 고객과 연관되어 있음을 의미 함)와 고객 인구 통계 데이터 (LastName, FirstName, DOB)입니다. , FirstName, DOB)에서 StoreID 및 LastName을 알고있는 고객 만 효율적으로 검색 할 수 있습니다.
반면, StoreID에 인덱스를 정의하고 LastName, FirstName, DOB 열을 포함하면 본질적으로 StoreID에 대해 두 개의 seek-index 술어를 수행 한 다음 포함 된 열에 대해 술어를 탐색 할 수 있습니다. 이렇게하면 StoreID로 시작하는 한 가능한 모든 검색 순열을 다룰 수 있습니다.