¿Qué índice se usará en este escenario?


11

SQL Server 2014 Standard Edition

Necesito encontrar la cantidad de vuelos que van hacia y desde ciudades específicas durante ciertos meses. P.ej

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

El esquema de la tabla está debajo.

Estoy tratando de estimar si es preferible el modelo de índice A o el modelo de índice B (a continuación) (toma muchas horas construir el índice, y el espacio en disco permite que solo exista uno a la vez, así que estoy tratando de mirar antes de saltar).

Desde mi experiencia, cualquier índice servirá. Estoy en lo cierto?

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

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

(O, mejor, ¿hay un índice binario o un mecanismo avanzado que pueda usar para abordar esto?)

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]

Respuestas:


18

El índice A es mejor para esta consulta. Cuando todas las condiciones en el WHEREson verificaciones de igualdad, excepto una que usa una condición de rango u INoperador en una columna, entonces esa última columna debe ser la última en el índice, después de todas las columnas que tienen una verificación de igualdad.

Esto permite que el optimizador use una búsqueda de índice para la primera fila que coincida con las condiciones y luego atraviese el índice hasta que encuentre una fila que no coincida. Todas las filas intermedias también coinciden.

Entonces, el mejor índice para esta consulta sería (to, from, date)(su modelo A) o (from, to, date).

El índice del modelo B tiene la fecha primero, por lo que no es el mejor, aunque sigue siendo un índice de cobertura para la consulta. Si se usara esto, el plan de consulta sería casi el mismo. Un índice busca encontrar la primera fila que coincida con la condición de rango ( date > '2016-02-28') y luego recorre el índice hasta que encuentre una fila que no coincida con date < '2016-04-01'. Pero todas las filas intermedias no necesariamente coinciden con las otras 2 condiciones, por lo que tendrían que verificarse con estas condiciones y (posiblemente muchas de ellas) rechazadas.

Entonces, si bien los planes serían similares, el plan modelo A solo tendría que pasar por la parte del índice que tiene todas las filas necesarias y solo ellas, mientras que el plan modelo B pasaría por una parte (posiblemente mucho) más grande del índice.


  • También sería mejor usar un formato 100% seguro para las fechas ( YYYYMMDD).

  • Y si desea las fechas en marzo, debe usar un cheque inclusivo-exclusivo:

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

    Garantizado para trabajar con tipos de fecha y fecha y hora. Su consulta actual incluirá también cualquier fila que tenga '2016-02-28'un tiempo diferente '00:00:00'(¿puede garantizar que no haya ninguna?) Que supongo que no desea. El método inclusivo-exclusivo también funcionará en años bisiestos (recordando que 2016 es un año bisiesto, por lo que también hubo una fecha del 29 de febrero que devolverá su consulta).

Lea también estas publicaciones de blog de Aaron Bertrand:

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.