Mengapa membuat indeks baru ini sangat meningkatkan kinerja ketika indeks yang ada menyertakan semua kolom dalam indeks baru?


19

Saya memiliki tabel Log dan LogItem; Saya sedang menulis kueri untuk mengambil beberapa data dari keduanya. Ada ribuan Logsdan masing-masing Logdapat 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 whereklausa 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.


Sebelum Anda membuat indeks nonclustered tambahan, apa yang ditunjukkan oleh rencana eksekusi aktual untuk penggunaan indeks?
Thomas Stringer

Apa yang meningkatkan kinerja sebesar 100%?

@ Hiu Pertanyaan bagus, saya tidak yakin. Ini adalah situasi debugging kinerja pertama saya. Saya pasti akan mengambil yang maju. Semua yang dikatakannya adalah 'Indeks hilang' dan dikatakan bidang mana.

@ Jeffe Inilah yang dikatakan SSMS: "Prosesor Kueri memperkirakan bahwa penerapan indeks berikut ini dapat meningkatkan biaya kueri sebesar 100%."

Jawaban:


21

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 dari column1dan column2. Tetapi jika Anda tahu column1dan column2juga, menemukan cabang yang tepat di pohon itu tidak ada artinya.


Apakah aman untuk mengasumsikan (secara umum) saya perlu satu indeks per set klausa "di mana" yang akan mencapai tabel itu?

Saya pernah melakukan percepatan besar permintaan orang lain hanya dengan memastikan itu menggunakan indeks dalam urutan yang tepat.

1
@Nate Secara luas, ya. Beberapa wheres mungkin tumpang tindih, jadi Anda mungkin memiliki indeks yang mencakup beberapa wheres; atau Anda dapat mengabaikan beberapa bagian whereklausa karena pengindeksan pada kolom tertentu tidak akan membantu (selektivitas rendah); tapi secara luas, ya.

@Nate Anda tidak ingin memiliki indeks lebih dari yang dibutuhkan. Setiap indeks yang SQL harus pertahankan menambahkan overhead sendiri. Jika Anda dapat menyusun ulang klausa WHERE Anda agar cocok dengan kolom N pertama pada indeks yang ada, itu akan membuat Anda sangat dekat tanpa menambahkan indeks tambahan.
Bahwa Chuck Guy

1
@ChuckBlumreich Urutan kolom dalam whereklausa tidak penting. Server akan selalu mengaturnya untuk memanfaatkan indeks yang ada. Ini hanya masalah memiliki indeks yang mencakup semua wherekolom yang diperlukan sebagai kolom pertama.

12

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 ParentLogIDdan DatabaseModified, 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) .


Jadi jika saya punya Columns (a, b, c, d, e, f)dan sebagian besar pertanyaan adalah ... WHERE A IN(...) AND B = 3indeks saya Index(a,b,c,d)yang bagus, tetapi itu tidak membantu jika saya punya ... WHERE A IN (...) AND D = 5itu sebabnya indeks saya baru saya buat, Index(a,d)kinerja meningkat begitu banyak, kan?

8
@Nate - benar. Anggap saja seperti buku telepon. Jika Anda tahu hanya nama depan seseorang, tidak mungkin untuk menemukan tanpa melihat seluruh buku karena ini terorganisir pada Nama Belakang, Nama Depan
JNK
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.