Diberikan beberapa tabel dengan kunci utama, misalnya:
CREATE TABLE Customers (
CustomerID int NOT NULL PRIMARY KEY,
FirstName nvarchar(50),
LastName nvarchar(50),
Address nvarchar(200),
Email nvarchar(260)
--...
)
kami memiliki kunci primer unik CustomerID
.
Secara tradisional saya mungkin perlu beberapa indeks penutup tambahan; misalnya untuk dengan cepat menemukan pengguna dengan salah satu CustomerID
atau Email
:
CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
(
CustomerID,
Email
)
Dan ini adalah jenis indeks yang telah saya buat selama beberapa dekade.
Tidak harus unik, tetapi sebenarnya memang begitu
Indeks itu sendiri ada untuk menghindari pemindaian tabel; ini adalah indeks penutup untuk membantu kinerja (indeks tidak ada sebagai kendala untuk menegakkan keunikan).
Hari ini saya ingat sedikit informasi - SQL Server dapat menggunakan fakta bahwa:
- sebuah kolom memiliki batasan kunci asing
- sebuah kolom memiliki indeks unik
- kendala dipercaya
untuk membantu mengoptimalkan eksekusi permintaannya. Bahkan, dari Panduan Perancangan Indeks SQL Server :
Jika data unik dan Anda ingin menerapkan keunikan, membuat indeks unik alih-alih indeks nonunique pada kombinasi kolom yang sama memberikan informasi tambahan untuk pengoptimal kueri yang dapat menghasilkan rencana pelaksanaan yang lebih efisien . Membuat indeks unik (lebih disukai dengan membuat batasan UNIK) direkomendasikan dalam kasus ini.
Mengingat bahwa indeks multi-kolom saya berisi kunci utama, indeks komposit ini akan de facto menjadi unik. Ini bukan kendala yang saya butuhkan terutama SQL Server untuk menegakkan selama setiap memasukkan atau memperbarui; tetapi faktanya indeks non-cluster ini unik.
Apakah ada keuntungan dalam menandai indeks unik de facto ini sebagai benar-benar unik?
BUAT INDEKS UNIK IX_Customers_CustomerIDEmail ON pelanggan ( ID Pelanggan, Surel )
Sepertinya saya bahwa SQL Server bisa cukup pintar untuk menyadari bahwa indeks saya sudah adalah unik berdasarkan fakta bahwa itu berisi kunci primer.
- Tapi mungkin tidak tahu ini, dan ada keuntungan bagi pengoptimal jika saya menyatakan indeks sebagai unik.
- Kecuali mungkin yang sekarang dapat menyebabkan pelambatan saat memasukkan dan memperbarui, di mana ia harus melakukan pemeriksaan keunikan - di mana sebelumnya tidak pernah harus sebelumnya.
- Kecuali ia tahu indeks dijamin sudah unik, karena mengandung kunci utama.
Saya tidak dapat menemukan panduan apa pun dari Microsoft tentang apa yang harus dilakukan ketika indeks komposit berisi kunci utama.
Manfaat indeks unik meliputi:
- Integritas data kolom yang ditentukan dipastikan.
- Informasi tambahan yang bermanfaat bagi pengoptimal kueri disediakan.
Haruskah saya menandai indeks komposit sebagai unik jika sudah berisi kunci utama? Atau dapatkah SQL Server mencari tahu ini sendiri?
sumber
Jawaban:
Mungkin tidak. Pengoptimal umumnya dapat menggunakan informasi tentang keunikan kolom kunci yang terkandung, jadi tidak ada keuntungan nyata.
Ada juga konsekuensi penting dari penandaan indeks yang unik pada rencana pembaruan yang memodifikasi kunci indeks itu untuk dipertimbangkan:
Mendirikan
Paket pembaruan per indeks (indeks tidak unik)
Rencana eksekusi:
Pengoptimal sering membuat keputusan berbasis biaya antara memperbarui indeks yang tidak tercakup per-baris (rencana 'sempit') atau per-indeks (rencana 'lebar'). Strategi default (kecuali untuk tabel OLTP dalam memori) adalah rencana yang luas.
Paket sempit (di mana indeks nonclustered dipertahankan pada saat yang sama dengan heap / clustered index) adalah pengoptimalan kinerja untuk pembaruan kecil. Optimalisasi ini tidak diterapkan untuk semua kasus - menggunakan fitur tertentu (seperti tampilan yang diindeks) berarti bahwa indeks terkait akan dipertahankan dalam rencana yang luas.
Informasi lebih lanjut: Mengoptimalkan T-SQL Query yang Mengubah Data
Dalam hal ini, saya telah menggunakan flag tanpa dokumen 8790 untuk memaksakan rencana pembaruan yang luas: Oleh karena itu rencana menunjukkan indeks berkerumun dan nonclustered dipertahankan secara terpisah.
Split mengubah setiap pembaruan menjadi pasangan hapus & sisipkan yang terpisah; Filter memfilter setiap baris yang tidak menghasilkan perubahan pada indeks.
Informasi lebih lanjut: ( Pembaruan yang tidak diperbarui ) oleh Tim QO SQL Server.
Paket pembaruan per indeks (indeks unik)
Rencana eksekusi:
Perhatikan operator Urutkan dan Perkecil tambahan saat indeks ditandai unik.
Pola Split-Sort-Collapse ini diperlukan saat memperbarui kunci indeks unik, untuk mencegah pelanggaran kunci unik menengah.
Informasi lebih lanjut: Mempertahankan Indeks Unik oleh Craig Freedman
Sortir secara khusus dapat menjadi masalah. Tidak hanya itu merupakan biaya tambahan yang tidak perlu, tetapi juga dapat tumpah ke disk jika perkiraan tidak akurat.
Tentang kunci yang tidak tercakup
Faktor lain yang perlu dipertimbangkan adalah bahwa struktur indeks nonclustered selalu unik, di setiap tingkat indeks, bahkan jika
UNIQUE
tidak ditentukan. Kunci pengelompokan - dan mungkin pemersatu jika indeks pengelompokan tidak ditandai unik - ditambahkan ke indeks tidak tercakup yang tidak unik di semua tingkatan.Sebagai konsekuensinya, definisi indeks berikut:
... sebenarnya berisi kunci (Email, CustomerID) di semua tingkatan. Oleh karena itu 'dicari' di kedua kolom:
Informasi lebih lanjut: Lebih Lanjut Tentang Tombol Indeks Nonclustered oleh Kalen Delaney
sumber
SQL tahu itu sudah unik (jika termasuk PK, itu tidak bisa lagi unik), terlepas dari apakah Anda secara eksplisit mengatakannya.
Perbedaan besar antara indeks non-unik dan indeks unik adalah bahwa indeks non-unik memerlukan kunci indeks berkerumun (dengan nilai uniquifier jika CIX tidak dinyatakan sebagai unik) di tingkat indeks yang lebih tinggi, tidak hanya di daun tingkat.
Dalam kasus Anda, Anda sudah memiliki CIX di kunci, yang berarti itu akan berada di setiap tingkat indeks.
Tapi Anda bisa membuat tabel yang memiliki PK terpisah (unik) dan CIX (tidak masalah). Kemudian buat indeks non-unik yang menyertakan PK pada kuncinya. Masukkan beberapa baris ke dalam tabel, termasuk beberapa nilai varchar yang mudah ditemukan untuk kolom CIX Anda. Masukkan cukup baris untuk menyebabkan beberapa level indeks Anda. Kemudian Anda dapat menggunakan DBCC IND untuk menemukan halaman di NCIX Anda, dan DBCC PAGE untuk membuka beberapa untuk melihat data, untuk melihat apakah nilai kunci CIX berada di level yang lebih tinggi.
sumber