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?
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?
Jawaban:
Kami akan melihat beberapa alasan lebih terinci, dan juga berbicara tentang beberapa batasan umum fitur.
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:
Kolom kunci Indeks Hilang dihasilkan dari kolom yang digunakan untuk memfilter hasil, seperti yang ada di:
Kolom Termasuk Indeks yang Hilang dihasilkan dari kolom yang diperlukan oleh kueri, seperti yang ada di:
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;
Pengelompokan ini juga bukan pada Lokasi.
SELECT TOP (20000) u.Location
FROM dbo.Users AS u
GROUP BY u.Location
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.
Tenang, bucko. Kita sudah sampai di sana.
Jika Anda mengaktifkan TF 2330 , permintaan indeks yang hilang tidak akan dicatat. Untuk mengetahui apakah Anda telah mengaktifkan ini, jalankan ini:
DBCC TRACESTATUS;
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 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.
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);
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.
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:
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:
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 ...
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);
Dan secara signifikan lebih sedikit berbunyi:
Tabel 'Posting'. Pindai hitungan 1, bacaan logis 5
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.