이 시나리오에서 어떤 인덱스가 사용됩니까?


11

SQL Server 2014 Standard Edition

특정 달에 특정 도시를 오가는 항공편 수를 찾아야합니다. 예 :

select count(*) 
from flights 
where flightTo_AirportCode = 'aaaa' 
and flightFrom_Airportcode = 'bbbb' 
and flightdate < '2016-04-01' 
and flightdate > '2016-02-28' ;

테이블 스키마는 다음과 같습니다.

인덱스 모델 A 또는 인덱스 모델 B (아래)가 바람직한 지 추정하려고합니다 (인덱스를 빌드하는 데 많은 시간이 걸리고 디스크 공간은 한 번에 하나만 존재할 수 있으므로 도약하기 전에 노력하고 있습니다).

내 경험에 비추어 볼 때 어느 쪽의 색인도 가능합니다. 내가 맞아?

  create index [modelA] on flights (flightTo_AirportCode, flightFrom_AirportCode, flightDate)

  create index [modelB] on flights (flightDate, flightTo_AirportCode, flightFrom_AirportCode)

(또는 더 나은 방법은 이진 인덱스 또는 고급 메커니즘으로 접근 할 수 있습니까?)

CREATE TABLE [dbo].[flights](
    [flightId] [uniqueidentifier] NOT NULL,
    [accountId] [uniqueidentifier] NULL,
    [flightDate] [datetime] NULL,
    [flightTo_AirportCode] [nvarchar](30) NULL,
    [flightFrom_AirportCode] [nvarchar](30) NULL,
    -- ... 45 more fields
    CONSTRAINT [PK_flight] PRIMARY KEY CLUSTERED 
(
    [flightId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 70) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

답변:


18

이 쿼리에는 인덱스 A가 더 좋습니다. 열의 WHERE범위 조건 또는 IN연산자를 사용하는 조건을 제외하고 등호 의 모든 조건 이 항등 검사 인 경우 , 항등 검사가있는 모든 열 뒤에 마지막 열이 색인에서 마지막이어야합니다.

이를 통해 옵티마이 저는 조건과 일치하는 첫 번째 행에 대한 인덱스 탐색을 사용하고 일치하지 않는 행을 찾을 때까지 인덱스를 탐색합니다. 사이의 모든 행도 일치합니다.

따라서이 쿼리에 가장 적합한 인덱스는 (to, from, date)(모델 A) 또는 (from, to, date)입니다.

모델 B 인덱스는 날짜가 먼저 있으므로 쿼리에 대한 커버링 인덱스이지만 최상의 날짜는 아닙니다. 이것이 사용 된 경우 쿼리 계획은 거의 동일합니다. 인덱스는 범위 조건 ( date > '2016-02-28')과 일치하는 첫 번째 행을 찾은 다음에 일치하지 않는 행을 찾을 때까지 인덱스를 탐색합니다 date < '2016-04-01'. 그러나 그 사이의 모든 행이 다른 두 조건과 반드시 ​​일치하지는 않으므로 이러한 조건과 비교하여 확인해야하고 (아마도 많은 수의) 거부됩니다.

따라서 계획은 비슷하지만 모델 A 계획은 필요한 모든 행이있는 색인의 일부만 통과하고 모델 B 계획은 (아마도) 큰 부분을 통과해야합니다. 인덱스.


  • 날짜 ( YYYYMMDD)에 100 % 안전한 형식을 사용하는 것이 가장 좋습니다 .

  • 그리고 3 월의 날짜를 원한다면 포괄적 인 검사를 사용해야합니다.

    AND flightdate >= '20160301' AND flightdate < '20160401' 

    날짜 및 날짜 / 시간 유형으로 작동하도록 보장합니다. 현재 쿼리에는 원하지 않는 '2016-02-28'시간과 다른 행이 포함되어 있습니다 (아무 것도 없다는 것을 '00:00:00'보장 할 수 있습니까?). 포괄적 배타적 방법은 윤년에도 적용됩니다 (2016 년은 윤년이므로 2 월 29 일 날짜와 쿼리가 반환 됨).

Aaron Bertrand의 다음 블로그 게시물을 읽어보십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.