Bu senaryoda hangi dizin kullanılacak?


11

SQL Server 2014 Standart Sürüm

Belirli aylar için belirli şehirlere gidiş ve dönüş uçuş sayısını bulmam gerekiyor. Örneğin

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

Tablo şeması aşağıdadır.

İndeks modelA veya dizin modelB (aşağıda) tercih edilebilir olup olmadığını tahmin etmeye çalışıyorum (dizin oluşturmak için birkaç saat sürer ve disk alanı bir kerede sadece biri var izin verir, bu yüzden ben sıçrama önce bakmaya çalışıyorum).

Deneyimlerime göre, her iki dizin de yapacak. Haklı mıyım?

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

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

(Veya daha iyisi, buna yaklaşmak için kullanabileceğim bir ikili dizin veya gelişmiş bir mekanizma var mı?)

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]

Yanıtlar:


18

A dizini bu sorgu için daha iyidir. Bir sütunda WHEREaralık koşulu veya INişleç kullanan durum dışındaki tüm koşullar eşitlik denetimleri olduğunda, eşitlik denetimine sahip tüm sütunlardan sonra dizinde son sütunun son olması gerekir.

Bu, optimize edicinin koşullarla eşleşen ilk satıra bir dizin araması kullanmasına ve ardından diziyle eşleşmeyen bir satır bulana kadar dizinin üzerinden geçiş yapmasına olanak tanır. Aradaki tüm satırlar da eşleşir.

Bu nedenle, bu sorgu için en iyi dizin ya (to, from, date)(model A) ya da olacaktır (from, to, date).

B modeli endeksi ilk tarihe sahiptir, bu yüzden hala sorgu için bir kaplama dizini olmasına rağmen en iyisi değildir. Bu kullanılırsa, sorgu planı hemen hemen aynı olacaktır. Bir dizin, aralık koşuluyla ( date > '2016-02-28') eşleşen ilk satırı bulmaya çalışır ve ardından diziyle eşleşmeyen bir satır bulana kadar dizinde geçiş yapar date < '2016-04-01'. Ancak aradaki tüm satırların diğer 2 koşulla eşleşmesi gerekmez, bu nedenle bu koşullara karşı kontrol edilmeleri gerekir ve (muhtemelen birçoğu) reddedilir.

Bu yüzden planlar benzer olsa da, A modeli planın sadece gerekli tüm satırlara sahip olan kısımdan ve sadece bunlardan geçmesi gerekirken, B modeli planı planın (muhtemelen çok daha büyük) indeks.


  • Tarihler için% 100 güvenli bir biçim kullanmak da en iyisidir ( YYYYMMDD).

  • Ve Mart ayında tarihleri ​​istiyorsanız, kapsamlı bir çek kullanmalısınız:

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

    Tarih ve datetime türleriyle çalışma garantisi. Mevcut sorgunuzda , istemediğinizi düşündüğüm '2016-02-28'bir zamandan farklı '00:00:00'( herhangi bir zaman olmadığını garanti edebilir misiniz?) Kapsayıcı-özel yöntem artık yıllarda da çalışacaktır (2016'nın artık bir yıl olduğunu hatırlatır, bu nedenle sorgunuzun geri döneceği 29 Şubat tarihi de vardır).

Aaron Bertrand tarafından gönderilen bu blog gönderilerini de okuyun:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.