Indeks mana yang akan digunakan dalam skenario ini?

11

SQL Server 2014 Edisi Standar

Saya perlu menemukan jumlah penerbangan ke dan dari kota-kota tertentu selama bulan-bulan tertentu. Misalnya

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

Skema tabel di bawah ini.

Saya mencoba memperkirakan apakah index modelA atau index modelB (di bawah) lebih disukai (butuh berjam-jam untuk membangun indeks, dan ruang disk hanya memungkinkan satu untuk ada pada satu waktu, jadi saya mencoba untuk melihat sebelum saya melompat).

Dari pengalaman saya, baik indeks akan melakukan. Apakah saya benar?

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

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

(Atau, lebih baik, apakah ada indeks biner atau mekanisme canggih yang bisa saya gunakan untuk mendekati ini?)

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 Reinstate Monica
sumber

Jawaban:

18

Indeks A lebih baik untuk kueri ini. Ketika semua kondisi dalam WHEREadalah pemeriksaan kesetaraan kecuali yang menggunakan kondisi jangkauan atau INoperator pada kolom, maka kolom terakhir harus terakhir dalam indeks, setelah semua kolom yang memiliki pemeriksaan kesetaraan.

Ini memungkinkan pengoptimal untuk menggunakan pencarian indeks ke baris pertama yang cocok dengan kondisi dan kemudian melintasi indeks sampai menemukan baris yang tidak cocok dengan itu. Semua baris di antaranya juga cocok.

Jadi, indeks terbaik untuk permintaan ini adalah (to, from, date)(model Anda A) atau (from, to, date).

Indeks B model memiliki tanggal pertama sehingga bukan yang terbaik, meskipun masih merupakan indeks penutup untuk kueri. Jika ini digunakan, rencana kueri akan hampir sama. Indeks berusaha menemukan baris pertama yang cocok dengan kondisi rentang ( date > '2016-02-28') dan kemudian melintasi indeks hingga menemukan baris yang tidak cocok dengan date < '2016-04-01'. Tetapi semua baris di antaranya tidak selalu cocok dengan 2 kondisi lain sehingga mereka harus diperiksa terhadap kondisi ini dan (mungkin banyak dari mereka) ditolak.

Jadi sementara rencana akan serupa, rencana model A hanya harus melalui bagian indeks yang memiliki semua baris yang diperlukan dan hanya mereka, sedangkan rencana model B akan melalui bagian (mungkin jauh) yang lebih besar dari indeks.


  • Akan lebih baik menggunakan format aman 100% untuk tanggal ( YYYYMMDD).

  • Dan jika Anda ingin tanggal pada bulan Maret, Anda harus menggunakan cek inklusif-eksklusif:

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

    Dijamin untuk bekerja dengan tipe tanggal dan waktu. Permintaan Anda saat ini akan mencakup juga setiap baris yang memiliki '2016-02-28'waktu berbeda dengan '00:00:00'(dapatkah Anda menjamin tidak ada?) Yang saya anggap tidak Anda inginkan. Metode inklusif-eksklusif juga akan berfungsi dalam tahun kabisat (mengingatkan bahwa 2016 adalah tahun kabisat sehingga ada tanggal 29 Februari dan kueri Anda akan kembali).

Baca juga posting blog ini oleh Aaron Bertrand:

ypercubeᵀᴹ
sumber