Qual índice será usado nesse cenário?

11

SQL Server 2014 Standard Edition

Preciso encontrar o número de voos de e para cidades específicas por determinados meses. Por exemplo

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

O esquema da tabela está abaixo.

Estou tentando estimar se o modelo de índice A ou o modelo de índice B (abaixo) é preferível (leva muitas horas para criar o índice e o espaço em disco permite que apenas exista um de cada vez, por isso estou tentando olhar antes de pular).

Da minha experiência, qualquer um dos índices serve. Estou certo?

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

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

(Ou, melhor, existe um índice binário ou mecanismo avançado que eu possa usar para abordar isso?)

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]
Jonesome Restabelecer Monica
fonte

Respostas:

18

O índice A é melhor para esta consulta. Quando todas as condições na WHEREverificação de igualdade são exceto uma que está usando uma condição de intervalo ou INoperador em uma coluna, a última coluna deve ser a última no índice, depois de todas as colunas que possuem uma verificação de igualdade.

Isso permite que o otimizador use uma busca de índice para a primeira linha que corresponda às condições e percorra o índice até encontrar uma linha que não corresponda a ela. Todas as linhas intermediárias também são compatíveis.

Portanto, o melhor índice para essa consulta seria (to, from, date)(seu modelo A) ou (from, to, date).

O índice do modelo B tem a data primeiro, portanto não é o melhor, embora ainda seja um índice de cobertura para a consulta. Se isso fosse usado, o plano de consulta seria quase o mesmo. Um índice procura encontrar a primeira linha que corresponde à condição do intervalo ( date > '2016-02-28') e, em seguida, percorre o índice até encontrar uma linha que não corresponde à date < '2016-04-01'. Mas todas as linhas intermediárias não coincidem necessariamente com as outras duas condições, portanto, elas precisam ser verificadas nessas condições e (possivelmente muitas delas) rejeitadas.

Assim, enquanto os planos seriam semelhantes, o plano do modelo A teria que passar apenas pela parte do índice que possui todas as linhas necessárias e somente elas, enquanto o plano do modelo B passaria por uma parte (possivelmente muito) maior do índice.


  • Também seria melhor usar um formato 100% seguro para datas ( YYYYMMDD).

  • E se você quiser as datas em março, use um cheque exclusivo:

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

    Garantido para trabalhar com tipos de data e data e hora. Sua consulta atual incluirá também qualquer linha que tenha '2016-02-28'um tempo diferente de '00:00:00'(você pode garantir que não exista?) Que suponho que não queira. O método inclusivo-exclusivo também funcionará em anos bissextos (lembrando que 2016 é um ano bissexto, portanto houve uma data de 29 de fevereiro e a sua consulta retornará).

Leia também os posts de Aaron Bertrand:

ypercubeᵀᴹ
fonte