각 쿼리 유형마다 별도의 인덱스가 필요합니까? 아니면 하나의 다중 열 인덱스가 작동합니까?


22

나는이 질문에 대한 답을 이미 알고 있지만 주제에 대해 더 많이 다루어야 할 것처럼 항상 느낍니다.

내 기본 이해는 일반적으로 말하면 주어진 시간에 쿼리 / 정렬 할 수있는 모든 필드를 포함하는 단일 인덱스는 유용하지 않을 가능성이 있지만이 유형의 것을 보았습니다. "누구나 우리가이 모든 것들을 인덱스에 넣는다면 데이터베이스는 그것을 사용하여 필요한 것을 찾을 수있다"고 생각했다.

다음과 같은 테이블을 상상해보십시오.

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

나는 포함한 단일 인덱스 볼 수 있습니다 name, customerId그리고 dateCreated필드.

그러나 내 이해는 그러한 색인이 예를 들어 다음과 같은 쿼리에서 사용되지 않는다는 것입니다.

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

이러한 쿼리의 경우 필드가 '첫 번째'인 customerIdand 및 dateCreated필드를 포함하는 인덱스가 더 나은 아이디어라고 생각 customerId합니다. 이렇게하면이 쿼리가 필요한 순서대로 필요한 것을 빠르게 찾을 수있는 방식으로 데이터를 구성하는 인덱스가 만들어집니다.

내가 처음 보는 것만 큼 자주 볼 또 다른 것은 각 필드의 개별 색인입니다. 그래서, 한 각 name, customerIddateCreated필드.

첫 번째 예와는 달리, 이런 형태의 배열은 때때로 적어도 부분적으로 유용한 것으로 보인다. 쿼리의 실행 계획은 적어도에서 인덱스를 사용 customerId하여 레코드를 선택하고 있지만 인덱스를 dateCreated필드 와 함께 사용하여 정렬 하지는 않음을 보여줄 수 있습니다.


특정 테이블 세트의 특정 쿼리에 대한 특정 답변은 일반적으로 실행 계획에서 수행 할 작업을 확인하고 그렇지 않으면 테이블 및 쿼리의 세부 정보를 가져 오는 것이기 때문에 이것이 광범위한 질문이라는 것을 알고 있습니다. 계정. 또한 특정 인덱스를 유지 관리하는 오버 헤드와 달리 쿼리가 얼마나 자주 실행될 수 있는지에 달려 있습니다.

그러나 내가 묻는 것은 인덱스의 일반적인 '시작점'이라고 생각합니다. 빈번하게 자주 쿼리되는 특정 쿼리와 WHERE 또는 ORDER BY 절의 필드에 대한 특정 인덱스를 갖는 아이디어가 의미가 있다고 생각합니까?

답변:


27

예제 쿼리가 해당 인덱스를 사용하지 않을 것입니다.

다음과 같은 경우 쿼리 플래너는 인덱스 사용을 고려합니다.

  • 여기에 포함 된 모든 필드는 쿼리에서 참조됩니다
  • 처음부터 시작하는 일부 필드가 참조됩니다

쿼리에서 사용하지 않는 필드로 시작하는 인덱스를 사용할 수 없습니다.

예를 들어,

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

다음과 같은 색인을 고려합니다.

[customerId]
[customerId], [dateCreated]
[customerId], [dateCreated], [name]

하지만:

[name], [customerId], [dateCreated]

그것은 모두 발견하는 경우 [customerId][customerId], [dateCreated], [name]필드 데이터의 균형의 추정에 의존하는 인덱스 통계에 따라 달라 다른 이상을 선호하는 결정을. [customerId], [dateCreated]정의 된 경우 특정 색인 힌트를 제공하지 않는 한 다른 두 가지를 선호해야합니다.

삽입 / 업데이트시 인덱스를 업데이트하는 데 필요한 추가 관리 및 인덱스를 저장하는 데 필요한 추가 공간이 절반으로 줄어듦에 따라이 방법은 거의 최적이 아니지만 내 경험의 모든 필드에 대해 하나의 인덱스를 정의하는 것은 드문 일이 아닙니다. 그것들은 결코 사용되지 않을 것입니다-그러나 DB가 쓰기가 많은 부하를 보지 않으면 초과 인덱스로도 성능이 나 빠지지 않을 것입니다.

테이블 또는 인덱스 스캔으로 인해 속도가 느려질 수있는 빈번한 쿼리에 대한 특정 인덱스는 일반적으로 좋은 생각이지만 성능 문제를 다른 것으로 교환 할 수 있으므로이를 과도하게 사용하지 마십시오. [customerId], [dateCreated]예를 들어 인덱스로 정의 하는 경우 쿼리 플래너는 [customerId]존재하는 경우 인덱스를 사용하는 쿼리에 사용할 수 있습니다 . 단지 사용하는 동안 [customerId]이 대신 하나의 RAM 공간에 대한 경쟁이 인덱스를 가진 결말에 의해 완화 될 수있는 복합 인덱스를 사용하는 것보다 약간 더 효율적인 것 (비록 당신의 전체 정상 근무 세트 맞는 쉽게 RAM에이 여분의 메모리 경쟁하지 않을 수 있습니다 경우 이슈).


+1; 훌륭한 정보, 특히 계획서 가 쿼리에 대해 첫 번째 필드 만 필요할 때 복합 인덱스를 사용할 있음을 상기 시켜줍니다.
Andrew Barber

6

예를 들어, 원래 질문에 대답하려면 테이블 뿐만 아니라 쿼리를 중심으로 인덱스를 설계 해야 합니다 . 인덱스의 필드 순서는 매우 중요합니다. 여러 쿼리에 최적 인 단일 인덱스를 디자인하는 것은 어렵고 절충해야합니다.

두 번째 요점과 관련하여 단일 개별 필드에 대한 많은 색인이 귀찮게 일반적입니다. 나는 항상 내 환경에서 그것을 보았습니다. 일반적으로 개발 팀이 DBA와 협력하여 적절한 색인을 디자인하지 않았다는 신호가 있습니다.

인덱스 디자인을위한 나의 전략은 다음과 같이 인덱스하는 것입니다.

  • WHERE에서 사용되는 필드 (선택 순서)
  • ORDER BY에서 사용되는 필드
  • 커버링 인덱스를 만들기 위해 필요한 경우 다른 필드를 포함

예를 들어,

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

아마도 (CustomerID, dateCreated) INCLUDE (id, name)에 대한 색인을 설계했을 것입니다. 이 커버링 인덱스는 쿼리가 원래 테이블에 도달 할 필요가 없으므로 성능이 크게 향상됩니다.

그러나이 예제는 거의 너무 간단합니다. 순전히 (CustomerID)의 순진 색인도 거의 성능을 발휘합니다 (각 고객에 대해 단일 담당자 만 있다고 가정하면 테이블에 대한 단일 책갈피 조회 만 필요함). 테이블에 대해 실행되는 다른 쿼리에 따라 (CustomerID, ID)에서 실제로 클러스터형 인덱스를 수행하는 것이 유리할 수도 있습니다 .


"테이블뿐만 아니라 쿼리를 중심으로 인덱스를 디자인해야합니다"및 예제가 매우 단순하다는 점에 대한 나머지 대답에 대해 +1입니다.
Andrew Barber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.