Saya punya pertanyaan SQL berikut:
SELECT
Event.ID,
Event.IATA,
Device.Name,
EventType.Description,
Event.Data1,
Event.Data2
Event.PLCTimeStamp,
Event.EventTypeID
FROM
Event
INNER JOIN EventType ON EventType.ID = Event.EventTypeID
INNER JOIN Device ON Device.ID = Event.DeviceID
WHERE
Event.EventTypeID IN (3, 30, 40, 41, 42, 46, 49, 50)
AND Event.PLCTimeStamp BETWEEN '2011-01-28' AND '2011-01-29'
AND Event.IATA LIKE '%0005836217%'
ORDER BY Event.ID;
Saya juga punya indeks di atas Event
meja untuk kolom TimeStamp
. Pemahaman saya adalah bahwa indeks ini tidak digunakan karena IN()
pernyataan itu. Jadi pertanyaan saya adalah adakah cara untuk membuat indeks untuk IN()
pernyataan khusus ini untuk mempercepat permintaan ini?
Saya juga mencoba menambahkan Event.EventTypeID IN (2, 5, 7, 8, 9, 14)
sebagai filter untuk indeks aktif TimeStamp
, tetapi ketika melihat rencana eksekusi sepertinya tidak menggunakan indeks ini. Setiap saran atau wawasan tentang ini akan sangat dihargai.
Di bawah ini adalah rencana grafis:
Dan di sini ada tautan ke file .sqlplan .
Jawaban:
Diberikan tabel bentuk umum berikut:
Indeks berikut bermanfaat:
Untuk kueri:
Filter memenuhi
AND
persyaratan klausa, kunci pertama indeks memungkinkan pencarian[TimeStamp]
untuk difilterEventTypeIDs
dan termasukDeviceID
kolom membuat indeks meliputi (karenaDeviceID
diperlukan untuk bergabung keDevice
tabel).Kunci kedua dari indeks -
EventTypeID
tidak sepenuhnya diperlukan (bisa juga berupaINCLUDEd
kolom); Saya telah memasukkannya ke dalam kunci karena alasan yang disebutkan di sini . Secara umum, saya menyarankan orang untuk setidaknyaINCLUDE
kolom dariWHERE
klausa indeks yang difilter .Berdasarkan permintaan yang diperbarui dan rencana eksekusi dalam pertanyaan, saya setuju bahwa indeks yang lebih umum yang disarankan oleh SSMS kemungkinan adalah pilihan yang lebih baik di sini, kecuali daftar yang difilter
EventTypeIDs
bersifat statis karena Aaron juga menyebutkan dalam jawabannya:Indeks yang disarankan (nyatakan unik jika sesuai):
Informasi kardinalitas dari rencana eksekusi (sintaksis tidak berdokumen, jangan gunakan dalam sistem produksi):
Kueri yang diperbarui (mengulangi
IN
daftar untukEventType
tabel membantu pengoptimal dalam kasus khusus ini):Perkiraan rencana eksekusi:
Paket yang Anda dapatkan kemungkinan akan berbeda karena saya menggunakan statistik dugaan. Poin umumnya adalah memberikan pengoptimal sebanyak mungkin informasi, dan memberikan metode akses (indeks) yang efisien pada
[Event]
tabel 4-juta baris .sumber
Sebagian besar biaya adalah scan indeks berkerumun, dan kecuali tabel ini benar-benar luas atau Anda tidak benar-benar membutuhkan semua kolom dalam output, saya percaya SQL Server bahwa ini adalah jalur optimal dalam skenario saat ini dengan tidak ada lagi yang berubah . Itu memang menggunakan pemindaian rentang (diberi label sebagai pencarian CI) untuk mempersempit rentang baris yang diminati, tetapi karena outputnya masih akan memerlukan pencarian atau pemindaian CI bahkan dengan indeks yang difilter yang Anda buat. ditargetkan pada kisaran ini, dan bahkan dalam kasus itu pemindaian CI mungkin masih termurah (atau setidaknya SQL Server memperkirakannya seperti itu).
Rencana eksekusi memberi tahu Anda bahwa indeks ini akan berguna:
Meskipun tergantung pada kemiringan data Anda, mungkin lebih baik sebaliknya, misalnya:
Tapi saya akan menguji keduanya untuk memastikan mana yang lebih baik, jika salah satu - perbedaan antara salah satu indeks dan apa yang Anda miliki sekarang mungkin hanya marjinal (terlalu banyak variabel untuk kita ketahui) dan Anda harus memperhitungkan bahwa tambahan indeks membutuhkan pemeliharaan tambahan, dan ini dapat mempengaruhi operasi DML Anda (masukkan / perbarui / hapus). Anda juga dapat mempertimbangkan untuk memasukkan kriteria filter dalam indeks ini seperti yang disarankan oleh @SQLKiwi , tetapi hanya jika itu adalah serangkaian nilai EventTypeID yang sering Anda cari. Jika itu mengatur perubahan dari waktu ke waktu, maka indeks yang difilter hanya akan berguna untuk permintaan khusus ini.
Dengan jumlah baris yang rendah, saya harus bertanya-tanya seberapa buruk kinerjanya saat ini? Kueri ini mengembalikan 3 baris (tetapi tidak ada indikasi berapa banyak baris yang ditolaknya). Berapa banyak baris dalam tabel?
sumber
Saya baru tahu bahwa SQL Server 2008 R2 benar-benar membuat saran indeks ketika saya menjalankan rencana eksekusi. Indeks yang disarankan ini membuat kueri berjalan sekitar 90% lebih cepat.
Indeks yang disarankan adalah sebagai berikut:
sumber