[sql] 인덱스의 열 순서는 얼마나 중요합니까?

인덱스 선언의 시작 부분에서 가장 선택적인 열을 넣어야한다고 들었습니다. 예:

CREATE NONCLUSTERED INDEX MyINDX on Table1
(
   MostSelective,
   SecondMost,
   Least
)

우선, 내가 말하고있는 것이 맞습니까? 그렇다면 인덱스의 열 순서를 다시 정렬하여 성능에 큰 차이가 있습니까? 그렇지 않으면 “행하기 좋은”방법입니까?

내가 묻는 이유는 DTA를 통해 쿼리를 넣은 후 기존 인덱스와 거의 동일한 열이 거의 동일한 인덱스를 다른 순서로 생성하는 것이 좋습니다. 누락 된 열을 기존 색인에 추가하고 잘 호출하는 것을 고려하고있었습니다. 생각?



답변

다음과 같은 색인을보십시오.

Cols
  1   2   3
-------------
|   | 1 |   |
| A |---|   |
|   | 2 |   |
|---|---|   |
|   |   |   |
|   | 1 | 9 |
| B |   |   |
|   |---|   |
|   | 2 |   |
|   |---|   |
|   | 3 |   |
|---|---|   |

첫 번째 열이 두 번째 열을 먼저 제한하는 것보다 더 많은 결과를 제거하므로 A를 먼저 제한하는 방법을 참조하십시오. 인덱스 통과 방법, 열 1, 열 2 등을 파악하면 주먹 패스에서 대부분의 결과를 제거하면 2 단계가 훨씬 빨라집니다.

다른 경우, 열 3에서 쿼리 한 경우 결과 집합을 좁히는 데 전혀 도움이되지 않기 때문에 옵티마이 저는 인덱스를 사용하지도 않습니다. 쿼리 할 때마다 다음 단계 전에 처리 할 결과 수를 좁 히면 성능이 향상됩니다.

인덱스도 이런 식으로 저장되므로 인덱스를 쿼리 할 때 첫 번째 열을 찾기 위해 인덱스를 역 추적하지 않습니다.

한마디로 : 아니오, 그것은 보여주기위한 것이 아니며 실제 성능상의 이점이 있습니다.


답변

열 순서가 중요합니다. 이제 올바른 순서는 쿼리 방법에 따라 다릅니다. 정확한 검색 또는 범위 스캔을 수행하기 위해 인덱스를 사용할 수 있습니다. 정확한 탐색은 인덱스의 모든 열에 대한 값이 지정되고 쿼리가 정확히 행에 도달하는 경우입니다. 탐색의 경우 열 순서는 관련이 없습니다. 범위 스캔은 일부 열만 지정된 경우이며이 경우 순서가 중요합니다. SQL Server는 가장 왼쪽 열이 지정된 경우에만 다음으로 가장 왼쪽 열이 지정된 경우에만 범위 검색에 인덱스를 사용할 수 있습니다. 당신은 (A, B, C)에 대한 인덱스가있는 경우이를위한 범위 스캔에 사용할 수 A=@a에 대한, A=@a AND B=@b하지만 하지 에 대한 B=@b위해, C=@cB=@b AND C=@c. 케이스 A=@a AND C=@cA=@a부분은 인덱스를 사용하지만 C=@cnot 은 사용합니다 (쿼리는 모든 B 값을 스캔하고로 A=@a건너 뛰지 않습니다 C=@c). 다른 데이터베이스 시스템에는 소위 ‘건너 뛰기 스캔’연산자가있어 외부 열이 지정되지 않은 경우 인덱스의 내부 열을 활용할 수 있습니다.

그 지식을 가지고 인덱스 정의를 다시 볼 수 있습니다. 인덱스 (MostSelective, SecondMost, Least)MostSelective컬럼이 지정된 경우에만 유효 합니다. 그러나 이것이 가장 선택 적이기 때문에 내부 컬럼의 관련성이 빠르게 저하됩니다. 더 나은 색인이 켜져 (MostSelective) include (SecondMost, Least)있거나 켜져 있는 경우가 종종 있습니다 (MostSelective, SecondMost) include (Least). 내부 열은 관련성이 적기 때문에 인덱스의 올바른 위치에 낮은 선택도 열을 배치하면 탐색에 노이즈가 발생하지 않으므로 중간 페이지 밖으로 이동하여 리프 페이지에만 유지하는 것이 좋습니다. 쿼리 적용 범위 목적. 즉, INCLUDE로 옮깁니다. Least열 크기가 커질수록 더 중요해 집니다. 이 인덱스는 다음을 지정하는 쿼리에만 혜택을 줄 수 있습니다.MostSelective 정확한 값 또는 범위로, 그리고 가장 선택적인 컬럼은 이미 후보 행을 상당히 제한합니다.

반면에 인덱스 (Least, SecondMost, MostSelective)는 실수로 보일 수 있지만 실제로는 매우 강력한 인덱스입니다. Least가장 바깥 쪽 쿼리로 열 이 있기 때문에 선택도가 낮은 열에 대한 결과를 집계해야하는 쿼리에 사용할 수 있습니다. 이러한 쿼리는 OLAP 및 분석 데이터웨어 하우스에서 널리 사용되며, 이러한 인덱스가 매우 적합한 경우입니다. 이러한 인덱스는 실제로 관련 클러스터의 큰 청크 ( Least일반적으로 일종의 범주 또는 유형을 나타내는 동일한 값) 에 물리적 레이아웃을 구성하고 분석 쿼리를 용이하게하기 때문에 우수한 클러스터형 인덱스를 만듭니다 .

불행히도 ‘정확한’순서는 없습니다. 쿠키 커터 레시피를 따르지 말고 대신 해당 테이블에 대해 사용할 쿼리 패턴을 분석하고 올바른 인덱스 열 순서를 결정하십시오.


답변

Remus에 따르면 워크로드에 따라 다릅니다.

그래도 수용 된 답변의 오도 된 측면을 다루고 싶습니다.

인덱스의 모든 열에서 동등 검색을 수행하는 쿼리의 경우 큰 차이가 없습니다.

아래는 두 개의 테이블을 만들고 동일한 데이터로 채 웁니다. 유일한 차이점은 하나의 키는 가장 선택적인 순서에서 가장 덜 선택적인 순서이고 다른 하나는 반대 순서입니다.

CREATE TABLE Table1(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);
CREATE TABLE Table2(MostSelective char(800), SecondMost TINYINT, Least  CHAR(1), Filler CHAR(4000) null);

CREATE NONCLUSTERED INDEX MyINDX on Table1(MostSelective,SecondMost,Least);
CREATE NONCLUSTERED INDEX MyINDX2 on Table2(Least,SecondMost,MostSelective);

INSERT INTO Table1 (MostSelective, SecondMost, Least)
output inserted.* into Table2
SELECT TOP 26 REPLICATE(CHAR(number + 65),800), number/5, '~'
FROM master..spt_values
WHERE type = 'P' AND number >= 0
ORDER BY number;

이제 두 테이블 모두에 대해 쿼리를 수행합니다 …

SELECT *
FROM   Table1
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~';

SELECT *
FROM   Table2
WHERE  MostSelective = REPLICATE('P', 800)
       AND SecondMost = 3
       AND Least = '~'; 

… 둘 다 지수 벌금을 사용하며 모두 동일한 비용이 부과됩니다.

여기에 이미지 설명을 입력하십시오

허용 된 답변의 ASCII 기술은 실제로 색인이 구성되는 방식이 아닙니다. Table1의 인덱스 페이지는 아래와 같습니다 (이미지를 클릭하면 전체 크기로 열림).

여기에 이미지 설명을 입력하십시오

인덱스 페이지에는 전체 키를 포함하는 행이 포함되어 있습니다 (이 경우 인덱스가 고유 한 것으로 선언되지 않았지만 이에 대한 자세한 정보는 여기서 무시할 수 있으므로 행 식별자에 추가 된 추가 키 열 이 있습니다 ).

위의 쿼리에서 SQL Server는 열의 선택성에 신경 쓰지 않습니다. 이 루트 페이지와 것을 발견의 이진 검색 수행 (PPP...,3,~ ) 입니다 >=(JJJ...,1,~ )< (SSS...,3,~ )그래서 페이지를 읽어야합니다 1:118. 그런 다음 해당 페이지에서 주요 항목을 이진 검색하고 아래로 이동할 리프 페이지를 찾습니다.

선택성 순서로 색인을 변경해도 이진 검색에서 예상되는 키 비교 수 또는 색인 검색을 수행하기 위해 탐색해야하는 페이지 수에는 영향을 미치지 않습니다. 기껏해야 키 비교 속도 약간 빨라질 수 있습니다.

때로는 가장 선택적인 인덱스를 먼저 주문하면 작업 부하의 다른 쿼리에 적합합니다.

예를 들어 작업 부하에 다음 두 가지 형식의 쿼리가 모두 포함되어있는 경우

SELECT * ... WHERE  MostSelective = 'P'

SELECT * ...WHERE Least = '~'

위의 색인 중 하나를 다루지 않습니다. MostSelective검색 및 조회 기능을 사용하여 계획을 세우기에 충분히 선택적이지만 쿼리에 Least대해서는 그렇지 않습니다.

그러나이 시나리오 (복합 인덱스의 선행 열 서브 세트에서 인덱스 탐색을 다루지 않음)는 인덱스가 도움이 될 수있는 쿼리 클래스 중 하나 일뿐입니다. 실제로 MostSelective단독으로 검색하지 않고 MostSelective, SecondMost항상 세 열 모두의 조합으로 검색하는 경우이 이론적 인 장점은 쓸모가 없습니다.

반대로 다음과 같은 쿼리

SELECT MostSelective,
       SecondMost,
       Least
FROM   Table2
WHERE  Least = '~'
ORDER  BY SecondMost,
          MostSelective 

쿼리를 다루고 탐색을 지원하고 원하는 순서로 행을 반환하여 부팅 할 수 있도록 일반적으로 처방 된 순서의 역순을 가하면 도움이됩니다.

이 조언의 자주 반복되는 부분이다 그러나 대부분에 그것의 잠재적 인 혜택에 대한 경험적 그래서 다른 쿼리 – 그리고 실제로보고를 대신 할 수 없습니다 당신의 작업.


답변

인덱스 선언의 시작 부분에서 가장 선택적인 열을 넣어야합니다.

옳은. 인덱스는 복합 열일 수 있으며 여러 열로 구성되며 순서는 가장 왼쪽 원칙으로 인해 중요합니다. 데이터베이스가 목록을 왼쪽에서 오른쪽으로 확인하고 정의 된 순서와 일치하는 해당 열 참조를 찾아야하기 때문입니다. 예를 들어, 열이있는 주소 테이블에 색인이있는 경우 :

  • 주소
  • 시티
  • 상태

address열을 사용하는 모든 쿼리 는 인덱스를 사용할 수 있지만 쿼리에 참조 city및 / 또는 state참조 만있는 경우 인덱스를 사용할 수 없습니다. 가장 왼쪽 열이 참조되지 않기 때문입니다. 쿼리 성능은 개별 인덱스 또는 순서가 다른 여러 복합물 중 어느 것이 최적인지 알려줍니다. 읽어보기 : Kimberley Tripp 의 Tipping Point


답변

다른 모든 대답은 잘못되었습니다.

주문을 선택할 때 복합 인덱스에서 개별 열의 선택성은 중요 하지 않습니다 .

간단한 사고 과정은 다음과 같습니다. 사실상, 색인은 관련된 열의 연결입니다.

그 이론적 근거를 제공하는 유일한 차이점은 문자열에서 이전과 나중에 다른 두 개의 ‘문자열’을 비교하는 것입니다. 이것은 총 비용의 작은 부분입니다. 하나의 답변에서 언급했듯이 “첫 번째 패스 / 두 번째 패스”는 없습니다.

그렇다면 어떤 순서를 사용해야합니까?

  1. 테스트 열 (들)을 시작 =으로, 어떤 순서.
  2. 그런 다음 하나의 범위 열을 고정하십시오.

예를 들어, 매우 낮은 선택도 열이 있어야 이 먼저 와서 :

WHERE deleted = 0  AND  the_datetime > NOW() - INTERVAL 7 DAY
INDEX(deleted, the_datetime)

색인에서 순서를 바꾸면 완전히 무시 deleted됩니다.

(열 순서를 정하기위한 규칙이 훨씬 더 많습니다.)


답변