Welcher Index wird in diesem Szenario verwendet?

11

SQL Server 2014 Standard Edition

Ich muss die Anzahl der Flüge finden, die für bestimmte Monate von und zu bestimmten Städten fliegen. Z.B

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

Das Tabellenschema ist unten.

Ich versuche zu schätzen, ob Indexmodell A oder Indexmodell B (unten) vorzuziehen ist (das Erstellen des Index dauert viele Stunden, und auf dem Speicherplatz kann jeweils nur einer vorhanden sein, daher versuche ich zu suchen, bevor ich springe).

Nach meiner Erfahrung reicht jeder Index aus. Habe ich recht?

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

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

(Oder, besser, gibt es einen Binärindex oder einen erweiterten Mechanismus, mit dem ich mich dem nähern kann?)

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 stellt Monica wieder her
quelle

Antworten:

18

Index A ist für diese Abfrage besser. Wenn alle Bedingungen in der WHEREListe Gleichheitsprüfungen sind, mit Ausnahme einer Bedingung, die eine Bereichsbedingung oder einen INOperator für eine Spalte verwendet, sollte diese letzte Spalte nach allen Spalten mit einer Gleichheitsprüfung die letzte im Index sein.

Auf diese Weise kann der Optimierer eine Indexsuche für die erste Zeile verwenden, die den Bedingungen entspricht, und dann den Index durchlaufen, bis eine Zeile gefunden wird, die nicht mit dieser übereinstimmt. Alle dazwischen liegenden Zeilen stimmen ebenfalls überein.

Der beste Index für diese Abfrage wäre also entweder (to, from, date)(Ihr Modell A) oder (from, to, date).

Der Modell-B-Index hat zuerst das Datum, ist also nicht der beste, obwohl er immer noch ein Deckungsindex für die Abfrage ist. Wenn dies verwendet würde, wäre der Abfrageplan fast der gleiche. Ein Index sucht nach der ersten Zeile, die der Bereichsbedingung ( date > '2016-02-28') entspricht, und durchläuft dann den Index, bis eine Zeile gefunden wird, die nicht mit der übereinstimmt date < '2016-04-01'. Alle dazwischen liegenden Zeilen stimmen jedoch nicht unbedingt mit den beiden anderen Bedingungen überein, sodass sie mit diesen Bedingungen verglichen und (möglicherweise viele von ihnen) abgelehnt werden müssten.

Während die Pläne ähnlich wären, müsste der Plan für Modell A nur den Teil des Index durchlaufen, der alle erforderlichen Zeilen und nur diese enthält, während der Plan für Modell B einen (möglicherweise viel) größeren Teil des Index durchlaufen würde Index.


  • Es ist auch am besten, ein 100% sicheres Format für Dates ( YYYYMMDD) zu verwenden.

  • Und wenn Sie die Daten im März möchten, sollten Sie einen Exklusiv-Exklusiv-Scheck verwenden:

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

    Garantiert für Datums- und Datums- / Uhrzeittypen. Ihre aktuelle Abfrage enthält auch jede Zeile, die '2016-02-28'nur eine andere Zeit hat als '00:00:00'(können Sie garantieren, dass es keine gibt?), Die Sie vermutlich nicht möchten. Die Inklusiv-Exklusiv-Methode funktioniert auch in Schaltjahren (erinnert daran, dass 2016 ein Schaltjahr ist, sodass es auch ein Datum für den 29. Februar gab, an das Ihre Anfrage zurückgegeben wird).

Lesen Sie auch diese Blog-Beiträge von Aaron Bertrand:

ypercubeᵀᴹ
quelle