Mengapa SQL Server tidak memiliki permintaan indeks yang hilang di DMVs atau Rencana Kueri?

14

Saya memiliki database SQL Server di mana kueri sangat lambat, dan ada banyak penguncian dan pemblokiran.

Ketika saya melihat DMV indeks yang hilang dan rencana kueri, tidak ada saran.

Mengapa demikian?

Erik Darling
sumber

Jawaban:

17

Ada banyak alasan mengapa Anda mungkin tidak memiliki permintaan indeks yang hilang!

Kami akan melihat beberapa alasan lebih terinci, dan juga berbicara tentang beberapa batasan umum fitur.

Keterbatasan Umum

Pertama, dari: Keterbatasan Fitur Indeks Hilang :

  • Itu tidak menentukan urutan untuk kolom yang akan digunakan dalam indeks.

Seperti yang tercantum dalam T&J ini: Bagaimana SQL Server menentukan urutan kolom kunci dalam permintaan indeks yang hilang? , urutan kolom dalam definisi indeks ditentukan oleh predikat Kesetaraan vs Ketidaksetaraan, dan kemudian posisi ordinal kolom dalam tabel.

Tidak ada tebakan pada selektivitas, dan mungkin ada pesanan yang lebih baik tersedia. Adalah tugas Anda untuk mencari tahu.

Indeks Khusus

Permintaan indeks yang hilang juga tidak mencakup indeks 'khusus', seperti:

  • Berkelompok
  • Tersaring
  • Dipartisi
  • Terkompresi
  • XML-ed
  • Ed spasial
  • Columnstore-d
  • Tampilan Terindeks-ed

Kolom apa yang dipertimbangkan?

Kolom kunci Indeks Hilang dihasilkan dari kolom yang digunakan untuk memfilter hasil, seperti yang ada di:

  • BERGABUNG
  • WHERE clause

Kolom Termasuk Indeks yang Hilang dihasilkan dari kolom yang diperlukan oleh kueri, seperti yang ada di:

  • PILIH
  • KELOMPOK OLEH
  • DIPESAN OLEH

Meskipun cukup sering, kolom tempat Anda memesan atau dikelompokkan dapat bermanfaat sebagai kolom utama. Ini kembali ke salah satu Batasan:

  • Ini tidak dimaksudkan untuk memperbaiki konfigurasi pengindeksan.

Misalnya, kueri ini tidak akan mendaftarkan permintaan indeks yang hilang, meskipun menambahkan indeks pada LastAccessDate akan mencegah kebutuhan untuk Mengurutkan (dan menumpahkan ke disk).

SELECT TOP (1000) u.DisplayName
FROM dbo.Users AS u
ORDER BY u.LastAccessDate DESC;

GILA

Pengelompokan ini juga bukan pada Lokasi.

SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location

GILA

Itu tidak terdengar sangat membantu!

Ya, tapi itu lebih baik daripada tidak sama sekali. Pikirkan permintaan indeks yang hilang seperti bayi yang menangis. Anda tahu ada masalah, tetapi terserah Anda sebagai orang dewasa untuk mencari tahu apa masalahnya.

Anda masih belum memberi tahu saya mengapa saya tidak memilikinya, ...

Tenang, bucko. Kita sudah sampai di sana.

Lacak Bendera

Jika Anda mengaktifkan TF 2330 , permintaan indeks yang hilang tidak akan dicatat. Untuk mengetahui apakah Anda telah mengaktifkan ini, jalankan ini:

DBCC TRACESTATUS;

Indeks Membangun Kembali

Membangun kembali indeks akan menghapus permintaan indeks yang hilang. Jadi sebelum Anda pergi, Hi-Ho-Silver-Away membangun kembali setiap indeks begitu sedikit fragmentasi menyelinap masuk, pikirkan tentang informasi yang Anda selesaikan setiap kali Anda melakukannya.

Anda mungkin juga ingin berpikir tentang Mengapa Mendefragmentasi Indeks Anda Tidak Membantu . Kecuali Anda menggunakan Columnstore .

Menambah, Menghapus, atau Menonaktifkan Indeks

Menambah, menghapus, atau menonaktifkan indeks akan menghapus semua permintaan indeks yang hilang untuk tabel itu. Jika Anda bekerja melalui beberapa perubahan indeks pada tabel yang sama, pastikan Anda membuat skrip semuanya sebelum melakukan apa pun.

Rencana Sepele

Jika sebuah rencana cukup sederhana, dan pilihan akses indeks cukup jelas, dan biayanya cukup rendah, Anda akan mendapatkan rencana sepele.

Ini secara efektif berarti tidak ada keputusan berdasarkan biaya yang harus dibuat oleh pengoptimal.

Via Paul White :

Rincian jenis kueri mana yang bisa mendapat manfaat dari Trivial Plan sering berubah, tetapi hal-hal seperti gabungan, subkueri, dan predikat ketidaksetaraan umumnya mencegah optimasi ini.

Ketika sebuah rencana sepele, fase optimasi tambahan tidak dieksplorasi, dan indeks yang hilang tidak diminta .

Lihat perbedaan antara permintaan ini dan paketnya :

SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2;

SELECT *
FROM dbo.Users AS u
WHERE u.Reputation = 2
AND 1 = (SELECT 1);

GILA

Paket pertama sepele, dan tidak ada permintaan yang ditampilkan. Mungkin ada kasus di mana bug mencegah muncul indeks hilang dalam rencana permintaan; mereka biasanya lebih andal masuk dalam indeks DMV yang hilang.

SARGability

Predikat di mana pengoptimal tidak akan dapat menggunakan indeks secara efisien bahkan dengan indeks dapat mencegah mereka untuk dicatat.

Hal-hal yang umumnya tidak SARGable adalah:

  • Kolom dibungkus fungsi
  • Kolom + SomeValue = SomePredicate
  • Kolom + AnotherColumn = SomePredicate
  • Kolom = @Variable ATAU @Variable IS NULL

Contoh:

SELECT *
FROM dbo.Users AS u
WHERE ISNULL(u.Age, 1000) > 1000;


SELECT *
FROM dbo.Users AS u
WHERE DATEDIFF(DAY, u.CreationDate, u.LastAccessDate) > 5000


SELECT *
FROM dbo.Users AS u
WHERE u.UpVotes + u.DownVotes > 10000000


DECLARE @ThisWillHappenWithStoredProcedureParametersToo NVARCHAR(40) = N'Eggs McLaren'
SELECT *
FROM dbo.Users AS u
WHERE u.DisplayName LIKE @ThisWillHappenWithStoredProcedureParametersToo 
      OR @ThisWillHappenWithStoredProcedureParametersToo IS NULL;

Tak satu pun dari kueri ini akan mendaftarkan permintaan indeks yang hilang. Untuk informasi lebih lanjut tentang ini, lihat tautan berikut:

Anda Sudah Memiliki Indeks Oke

Ambil indeks ini:

CREATE INDEX ix_whatever ON dbo.Posts(CreationDate, Score) INCLUDE(OwnerUserId);

Tampaknya baik untuk permintaan ini:

SELECT p.OwnerUserId, p.Score
FROM dbo.Posts AS p
WHERE p.CreationDate >= '20070101'
AND   p.CreationDate < '20181231'
AND   p.Score >= 25000
AND 1 = (SELECT 1)
ORDER BY p.Score DESC;

Rencananya adalah ...

GILA

Tetapi karena kolom kunci utama adalah untuk predikat kurang selektif, kami akhirnya melakukan lebih banyak pekerjaan daripada yang seharusnya:

Tabel 'Posting'. Pindai hitungan 13, berbunyi logis 136890

Jika kami mengubah urutan kolom kunci indeks, kami melakukan lebih sedikit pekerjaan:

CREATE INDEX ix_whatever ON dbo.Posts(Score, CreationDate) INCLUDE(OwnerUserId);

GILA

Dan secara signifikan lebih sedikit berbunyi:

Tabel 'Posting'. Pindai hitungan 1, bacaan logis 5

SQL Server Membuat Indeks Untuk Anda

Dalam kasus tertentu, SQL Server akan memilih untuk membuat indeks dengan cepat melalui spool indeks. Ketika spool indeks hadir, permintaan indeks yang hilang tidak akan. Tentunya menambahkan indeks sendiri bisa menjadi ide yang bagus, tetapi jangan mengandalkan SQL Server untuk membantu Anda mengetahuinya.

GILA

Erik Darling
sumber