Mengapa Tampilan Indeks tidak mengizinkan indeks cluster tidak unik?

12

Saya telah mencari menggunakan Indexed Views untuk meningkatkan kinerja pada beberapa pandangan kami yang paling umum digunakan.

Namun Indexed Views tidak mendukung indeks cluster tidak unik yang sedikit bertentangan dengan prioritas yang ditetapkan oleh sisa struktur database.

Sebagai contoh, berikut adalah versi sederhana dari beberapa tabel kami.

-Groups-
Group ID    GroupName

-Users-
UserKey    UserName    FullName     GroupID

Indeks berada di Groups.GroupID (Non-clustered) dan Users.GroupID (Clustered). Kunci yang dikelompokkan berada di GroupID di tabel Users sebagai rentang pengguna yang paling umum diambil. Jelas Anda akan memiliki banyak pengguna per grup, jadi indeks berkerumun ini tidak unik.

Ini membuat saya sedikit tidak yakin tentang bagaimana mengikuti prioritas ini ketika mengindeks pandangan saya seperti contoh ini, karena saya tidak dapat memiliki indeks cluster yang tidak unik.

ConsumableID    ConsumableVariantID AllowThresholdOverwrite FullPath    GroupID ManufacturerID  Type    ModelID
101              29                 1                       0.1.2.4.    4       3               3       2

Pada kenyataannya, satu-satunya nilai pada View ini yang selalu unik adalah kolom ConsumableID, jadi saya tidak punya banyak pilihan untuk menempatkan indeks saya di mana.

Mengapa Tampilan tidak mengizinkan indeks cluster non-unik ketika tabel biasa melakukannya?

Ramah tamah
sumber
3
Ada penjelasan yang sangat singkat di dekat bagian bawah halaman ini yang berjudul 'Mengapa indeks pertama pada tampilan harus DITENTU dan UNIK?' tetapi tidak banyak detail. Saya pasti akan tertarik mendengar penjelasan yang lebih rinci.
Steve Pettifer
5
Beberapa komentar: 1 - Tidak ada alasan Anda tidak dapat mengelompok (GroupID, UserID). Jangan membatasi diri Anda pada satu kolom untuk kunci. 2 - Saya membayangkan batasan untuk tampilan adalah karena ini adalah objek data tambahan yang harus memiliki baris yang mudah diikat ke indeks NC. Untuk sebuah tabel, kunci CI non-unik akan ditambahkan int untuk itu, tapi saya pikir itu akan lebih menantang dengan tampilan yang diindeks karena itu bukan tabel yang sebenarnya tetapi perlu MEMILIH tabel yang sebenarnya.
JNK

Jawaban:

22

Penjelasan berikut diberikan dalam Artikel Teknis Microsoft ini :

Mengapa indeks pertama pada tampilan harus CLUSTERED dan UNIQUE?

Itu harus UNIK untuk memungkinkan pencarian mudah catatan dalam tampilan dengan nilai kunci selama pemeliharaan tampilan diindeks, dan untuk mencegah penciptaan tampilan dengan duplikat, yang akan memerlukan logika khusus untuk mempertahankan. Itu harus dikelompokkan karena hanya indeks berkerumun dapat menegakkan keunikan dan menyimpan baris pada saat yang sama.

SQL Server menggunakan sistem aljabar delta untuk menjaga tampilan indeks sejalan dengan basis data. Ini juga secara otomatis menggabungkan operator rencana permintaan tampilan untuk setiap permintaan DML yang memengaruhi satu atau lebih tampilan yang diindeks. Memiliki indeks pengelompokan unik pada tampilan sangat menyederhanakan detail implementasi.

Pengaturan saat ini memungkinkan untuk bentuk pohon operator pemeliharaan bentuk tetap untuk dimasukkan dalam pohon permintaan DML dasar, memberikan ortogonalitas yang juga menyederhanakan pengujian. Pada akhirnya, pandangan yang diindeks dapat ditingkatkan satu hari untuk mendukung indeks cluster yang tidak unik, tetapi sekali lagi semua hal dimungkinkan karena waktu yang tidak terbatas dan sumber daya tanpa batas (tidak ada yang berlaku untuk tim pengembangan SQL Server pada saat penulisan).

Untuk contoh yang menunjukkan bagaimana pembuatan rencana kueri pembaruan yang rumit bisa, dan seberapa mudah bug halus dapat merayap masuk, lihat contoh bug yang terjadi dengan MERGEdan indeks yang difilter ini (fitur yang memiliki koneksi dekat dengan tampilan yang diindeks).

Paul White 9
sumber
2
Bug serupa dapat terjadi jika Anda mencoba memperbarui tampilan yang diindeks yang memiliki GROUP BYklausa tetapi tidak semua ekspresi pengelompokan adalah kunci dalam indeks berkerumun. Ini berlaku pada SQL Server 2014.
Quassnoi
4

Dalam SQL Server semua kunci indeks harus unik secara internal. Ini diperlukan untuk mendapatkan kunci kunci yang membahas tepat satu baris. Ini juga diperlukan untuk pemeliharaan indeks. Bayangkan sebuah NCI pada kolom yang hanya memiliki satu nilai di dalamnya (100% duplikat). Jika satu baris dihapus dari tabel, mesin penyimpanan harus menemukan baris NCI yang sesuai dan menghapusnya juga. Jika semua baris NCI tidak bisa dibedakan, ini tidak mungkin.

Jadi Anda melihat bahwa CI pada tampilan harus (secara internal) unik agar mesin dapat bekerja.

Jika Anda tidak membuat indeks SQL Server unik masih membuatnya unik secara internal. Dalam kasus NCI pada tabel heap, ia menambahkan bookmark baris. Dalam kasus CI non-unik itu menambahkan kolom uniquifier. Dalam kasus NCI di atas meja dengan CI, ia menambahkan kolom kunci CI yang belum Anda tentukan sendiri (ini mungkin termasuk uniquifier).

Tidak ada kolom jelas yang dapat ditambahkan jika ada tampilan yang diindeks. Jadi SQL Server tidak dapat secara otomatis melakukan ini.

Biasanya, cukup jelas bagi manusia kolom apa yang dapat Anda tambahkan untuk membuat tampilan memiliki seperangkat kolom unik untuk digunakan dalam CI. Ini biasanya kolom PK atau CI dari salah satu tabel yang mendasarinya. Jika tampilan memiliki GROUP BYindeks Anda biasanya pada tombol pengelompokan.

usr
sumber
2
Saya sangat menyarankan untuk merevisi ungkapan dari jawaban ini. Meskipun berisi poin yang valid mengenai pertanyaan asli, mungkin terlihat seperti itu menunjukkan bahwa semua indeks yang tidak unik mengandung penguning, yang tidak terjadi.
spaghettidba
@spaghettidba terima kasih, saya tidak menyadarinya. Semoga lebih baik sekarang.
usr
Maaf, belum. Anda mencampurkan dua hal bersama. Indeks nonclustered tidak harus unik dan tidak unik secara internal: Anda tidak membuat poin ini cukup jelas. Segala sesuatu yang Anda katakan dalam jawaban Anda hanya berlaku untuk indeks berkerumun.
spaghettidba
@spaghettidba NCI selalu unik secara internal. Mereka selalu dapat menampilkan semua kunci CI sebagai bagian dari rencana kueri. Lihat pastebin.com/vkGHpCsR Halaman data NCI berisi kedua kolom.
usr
Saya melihat dari mana Anda berasal. Beberapa daun dapat berbagi kunci indeks yang sama, tetapi kunci pengelompokan selalu termasuk dalam NCI. Apakah cukup dengan mengatakan bahwa mereka selalu unik secara internal? Saya kira tidak.
spaghettidba