Який індекс буде використаний у цьому сценарії?


11

Стандартне видання SQL Server 2014

Мені потрібно знайти кількість рейсів, які належать до конкретних міст і до них за певні місяці. Напр

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

Схема таблиці наведена нижче.

Я намагаюся оцінити, чи є кращою модель індексуА або індекс-модель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 план проходитиме через (можливо набагато більшу) частину покажчик.


  • Краще також використовувати 100% безпечний формат для дат ( YYYYMMDD).

  • А якщо ви хочете побачити в березні, вам слід скористатись ексклюзивним чеком:

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

    Гарантована робота з типом дати та дати. Ваш поточний запит буде також включати будь-яку рядок, який має '2016-02-28'час, який відрізняється від часу '00:00:00'(чи можете ви гарантувати, що такого немає?), Якого, я вважаю, ви не хочете Метод ексклюзивного ексклюзиву також буде працювати у високосні роки (нагадуючи, що 2016 рік є високосним, тому відбулася дата 29 лютого, а також ваш запит повернеться).

Читайте також ці повідомлення в блозі Аарона Бертран:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.