Saya memiliki tabel Log dan LogItem; Saya sedang menulis kueri untuk mengambil beberapa data dari keduanya. Ada ribuan Logs
dan masing-masing Log
dapat memiliki hingga 125LogItems
Kueri yang dipermasalahkan rumit jadi saya melewatkannya (jika seseorang berpikir itu penting, saya mungkin dapat mempostingnya), tetapi ketika saya menjalankan paket SSMS Estimated Query, ia memberi tahu saya bahwa indeks Non-Clustered baru akan meningkatkan kinerja hingga 100% .
Existing Index: Non-clustered
Key Colums (LogItem): ParentLogID, DateModified, Name, DatabaseModified
Query Plan Recommendation
CREATE NONCLUSTERED INDEX [LogReportIndex]
ON [dbo].[LogItem] ([ParentLogID],[DatabaseModified])
Hanya untuk bersenang-senang, saya membuat indeks baru ini dan menjalankan kueri dan sangat mengejutkan saya, sekarang butuh ~ 1 detik untuk menjalankan kueri, ketika sebelum 10+ detik.
Saya berasumsi bahwa indeks saya yang ada akan mencakup permintaan baru ini, jadi pertanyaan saya adalah mengapa membuat indeks baru pada satu-satunya kolom yang digunakan dalam permintaan baru saya meningkatkan kinerja? Haruskah saya memiliki indeks untuk setiap kombinasi kolom unik yang digunakan dalam where
klausa saya ?
catatan: Saya tidak berpikir ini karena SQL Server sedang melakukan caching hasil saya, saya menjalankan kueri sekitar 25-30 kali sebelum saya membuat indeks dan secara konsisten butuh 10-15 detik, setelah indeks sekarang konsisten ~ 1 atau kurang.
sumber
Jawaban:
Urutan kolom dalam indeks adalah penting. Jika penyaringan memerlukan kolom 1 dan 4 dari indeks, indeks tidak akan membantu. Ini hanya berguna saat memfilter dengan N kolom pertama berturut-turut.
Ini karena indeks adalah pohon. Anda tidak dapat secara efisien memilih semua node dari pohon di mana
column3 = something
, karena mereka tersebar di semua tempat lain, milik nilai yang berbeda daricolumn1
dancolumn2
. Tetapi jika Anda tahucolumn1
dancolumn2
juga, menemukan cabang yang tepat di pohon itu tidak ada artinya.sumber
where
s mungkin tumpang tindih, jadi Anda mungkin memiliki indeks yang mencakup beberapawhere
s; atau Anda dapat mengabaikan beberapa bagianwhere
klausa karena pengindeksan pada kolom tertentu tidak akan membantu (selektivitas rendah); tapi secara luas, ya.where
klausa tidak penting. Server akan selalu mengaturnya untuk memanfaatkan indeks yang ada. Ini hanya masalah memiliki indeks yang mencakup semuawhere
kolom yang diperlukan sebagai kolom pertama.The terdepan dari indeks adalah apa yang penting.
Selama kueri Anda "ditutupi" oleh indeks terdepan, itu akan efisien. Database indeks biasanya diimplementasikan sebagai B-Trees dan struktur B-Tree menentukan bahwa pencarian harus dilakukan dalam urutan tertentu, itulah sebabnya urutan bidang dalam indeks komposit penting.
Jika Anda memiliki "lubang", misalnya jika Anda mencari
ParentLogID
danDatabaseModified
, tetapi hanya memiliki indeks{ParentLogID, DateModified, Name, DatabaseModified}
, maka hanya{ParentLogID}
bagian dari indeks yang dapat digunakan secara efisien.(CATATAN: Beberapa DBMS dapat memanfaatkan
{DatabaseModified}
porsi tersebut melalui "lewati pemindaian", tetapi bahkan jika DBMS Anda melakukannya, itu jauh lebih efisien daripada akses indeks biasa) .sumber
Columns (a, b, c, d, e, f)
dan sebagian besar pertanyaan adalah... WHERE A IN(...) AND B = 3
indeks sayaIndex(a,b,c,d)
yang bagus, tetapi itu tidak membantu jika saya punya... WHERE A IN (...) AND D = 5
itu sebabnya indeks saya baru saya buat,Index(a,d)
kinerja meningkat begitu banyak, kan?