Untuk tabel dengan kolom identitas, haruskah PK / indeks unik berkerumun atau tidak berkerumun dibuat untuk kolom identitas?
Alasannya adalah indeks lain akan dibuat untuk kueri. Kueri yang menggunakan indeks nonclustered (di heap) dan mengembalikan kolom yang tidak tercakup oleh indeks akan menggunakan I / O (LIO) yang kurang logis karena tidak ada indeks clustered tambahan b-tree mencari langkah-langkah?
create table T (
Id int identity(1,1) primary key, -- clustered or non-clustered? (surrogate key, may be used to join another table)
A .... -- A, B, C have mixed data type of int, date, varchar, float, money, ....
B ....
C ....
....)
create index ix_A on T (A)
create index ix_..... -- Many indexes can be created for queries
-- Common query is query on A, B, C, ....
select A, B
from T
where A between @a and @a+5 -- This query will have less LIO if the PK is non-clustered (seek)
select A, B, C
from T
where B between @a and @a+5
....
PK yang dikelompokkan pada kolom identitas baik karena:
Ini meningkat secara monoton sehingga tidak ada halaman yang terbelah saat memasukkan. Dikatakan insert massal bisa secepat pada tabel heap (nonclustered)
Itu sempit
Namun, apakah pertanyaan dalam pertanyaan akan lebih cepat tanpa mengaturnya berkerumun?
** Pembaruan: ** Bagaimana jika itu Id
adalah FK dari tabel lain dan akan bergabung dalam beberapa pertanyaan?
Jawaban:
Secara default PK dikelompokkan dan dalam kebanyakan kasus, ini baik-baik saja. Namun, pertanyaan mana yang harus ditanyakan:
Indeks PK dan Clustered adalah 2 perbedaan:
Sekarang kita berakhir dengan 2 pertanyaan:
Tergantung bagaimana:
Pertama, apakah Anda memerlukan indeks berkerumun? Jika Anda memasukkan massal, lebih efisien untuk menyimpan data yang tidak terurut ke HEAP (dibandingkan data yang dipesan dalam sebuah cluster). Ini menggunakan RID (Pengidentifikasi Baris, 8 byte) untuk secara unik mengidentifikasi baris dan menyimpannya di halaman.
Indeks yang dikelompokkan tidak boleh berupa nilai acak. Data di tingkat daun akan disimpan dan dipesan oleh kunci indeks. Karena itu ia harus tumbuh terus menerus untuk menghindari fragmentasi atau pemisahan halaman. Jika ini tidak dapat dicapai oleh PK, Anda harus mempertimbangkan kunci lain sebagai kandidat berkerumun. Indeks yang dikelompokkan pada kolom identi, GUID berurutan atau bahkan sesuatu seperti tanggal penyisipan baik-baik saja dari sudut pandang sekuensial karena semua baris akan ditambahkan ke halaman daun terakhir. Di sisi lain, sementara pengidentifikasi unik mungkin berguna untuk kebutuhan bisnis Anda sebagai PK, mereka tidak boleh dikelompokkan (mereka secara acak dipesan / dihasilkan).
Jika setelah beberapa data dan analisis kueri, Anda mengetahui bahwa Anda sebagian besar menggunakan indeks yang sama untuk mendapatkan data Anda sebelum melakukan pencarian kunci di PK berkerumun, Anda dapat menganggapnya sebagai indeks berkerumun meskipun mungkin tidak secara unik mengidentifikasi data Anda.
Kunci indeks berkerumun terdiri dari semua kolom yang ingin Anda indeks. Kolom unik (4 byte) ditambahkan jika tidak ada batasan unik di atasnya (nilai inkremental untuk duplikat, nol sebaliknya). Kunci indeks ini kemudian akan disimpan satu kali untuk setiap baris di tingkat daun dari semua indeks yang tidak tercakup. Beberapa dari mereka juga akan disimpan beberapa kali pada tingkat menengah (cabang) antara akar dan tingkat daun pohon indeks (pohon-B). Jika kunci terlalu besar, semua indeks yang tidak berkerumun akan menjadi lebih besar, akan membutuhkan lebih banyak penyimpanan dan lebih banyak IO, CPU, memori, ... Jika Anda memiliki PK pada nama + tanggal lahir + negara, sangat mungkin bahwa kunci ini bukan kandidat yang baik. Itu terlalu besar untuk indeks berkerumun. Uniqueidentifier menggunakan NEWSEQUENTIALID () biasanya tidak dianggap sebagai kunci sempit (16 byte) meskipun berurutan.
Kemudian setelah Anda menemukan cara mengidentifikasi baris secara unik di tabel Anda, Anda bisa menambahkan PK. Jika Anda pikir Anda tidak akan menggunakannya dalam permintaan Anda, jangan buat itu berkerumun. Anda masih dapat membuat indeks nonclustered lain jika suatu saat Anda perlu menanyakannya. Perhatikan bahwa PK akan secara otomatis membuat indeks unik.
Indeks yang tidak dikelompokkan akan selalu berisi kunci yang dikelompokkan. Namun, jika kolom yang diindeks (+ kolom kunci) mencakup, tidak akan ada pencarian kunci dalam indeks berkerumun. Jangan lupa Anda juga dapat menambahkan Sertakan dan Di mana ke indeks yang tidak berkerumun. (Gunakan dengan bijak)
Indeks Clustered harus unik dan sesempit mungkin. Indeks Clustered tidak boleh berubah dari waktu ke waktu dan harus dimasukkan secara bertahap.
Sekarang saatnya untuk menulis beberapa SQL yang akan membuat tabel, indeks clustered dan nonclustered dan kendala.
Ini semua teoretis karena kami tidak tahu model data dan tipe data Anda yang digunakan (A dan B).
sumber
Jika Anda bertanya apakah default untuk kunci utama pada kolom identitas (khususnya) harus nonclustered, saya akan mengatakan tidak. Sebagian besar tabel mendapat manfaat dari memiliki indeks berkerumun, jadi membuat standar berkerumun untuk batasan kunci primer mungkin membantu secara keseluruhan, terutama untuk pengguna baru SQL Server.
Seperti halnya hampir semua opsi, selalu ada keadaan yang berbeda di mana satu lebih disukai daripada yang lain, tetapi DBA yang berpengalaman harus menyadari default, dan dapat menimpanya jika perlu. Lihat juga Tanya Jawab terkait, Kapan kunci primer harus dinyatakan nonclustered? .
Ya, tetapi dengan peringatan.
Pencarian RID memang lebih efisien daripada pencarian Kunci. Bahkan jika semua halaman yang diperlukan dalam memori (sangat mungkin untuk tingkat atas indeks), ada biaya CPU yang terkait dengan menavigasi indeks b-tree clustered. Sebagai akibatnya, SQL Server biasanya dapat melakukan pencarian RID lebih banyak daripada pencarian Kunci per unit waktu CPU.
Peringatan
Hal di atas tidak sering menjadi faktor penentu ketika memutuskan apakah akan menyusun tabel sebagai tumpukan atau tidak. Harus tidak praktis untuk menghindari pencarian (menggunakan indeks penutup), dan jumlah pencarian harus cukup besar untuk memiliki efek yang terukur (dan penting) pada kinerja, mengingat lingkungan perangkat keras dan beban kerja.
Tidak benar-benar praktis untuk mencakup semua aspek dari debat heap vs clustered index dalam jawaban ini, tetapi saya akan mengatakan bahwa ada beberapa alasan bagus untuk lebih memilih untuk menyusun tabel sebagai heap secara umum. Bagi saya, memilih jenis desain yang diusulkan dalam pertanyaan akan memerlukan analisis yang sangat hati-hati sebelum implementasi, dan harus memenuhi standar yang tinggi. Argumen umum tentang 'skalabilitas' tidak akan cukup.
Mengenai pembaruan untuk pertanyaan tentang bergabung, menilai dampak kehilangan indeks berkerumun pada rencana pelaksanaan akan menjadi bagian dari analisis yang disebutkan di atas. Jika nested loops joins digunakan, sangat nyaman untuk memiliki indeks berkerumun pada kunci gabungan karena semua kolom dari baris segera tersedia tanpa pencarian.
Pengalaman saya sendiri adalah bahwa memiliki indeks pengelompokan unik pada kolom identitas sering kali bermanfaat, semua hal dipertimbangkan. Saya telah menemukan tumpukan bermasalah dalam hal manajemen ruang, dan saya juga harus menyebutkan bahwa beberapa fitur SQL Server memerlukan indeks berkerumun unik untuk berfungsi.
sumber
Sebenarnya, Anda tidak perlu Indeks Berkelompok atau Kunci Utama untuk dibuat, karena Indeks Unik dan Indeks Non-Unik dapat menangani pekerjaan. SQL Server telah mendukung Indeks Clustered sejak setidaknya versi 1.1, tetapi Kunci Primer hanyalah sebuah "konsep" yang diprogram oleh pemrogram dengan mendefinisikan indeks yang unik.
Tapi sepertinya Primary Key dan Clustered Indexes adalah konsep yang berharga di sebagian besar basis data.
Mari kita lihat dokumentasi SQL Server untuk melihat deskripsi sebagian dari beberapa opsi pengindeksan seperti yang ditunjukkan di bawah ini.
Indeks Clustered: https://msdn.microsoft.com/en-us/library/ms190457.aspx
Kunci Utama: https://msdn.microsoft.com/en-us/library/ms190457.aspx
Sebuah tabel hanya dapat berisi satu kendala PRIMARY KEY.
Semua kolom yang didefinisikan dalam batasan PRIMARY KEY harus didefinisikan sebagai NOT NULL.
Kunci Utama dapat dibuat sebagai Indeks Clustered (default jika tidak ada Indeks Clustered) atau Indeks Non-Clustered.
Indeks Unik: https://msdn.microsoft.com/en-us/library/ms187019.aspx
Saat Anda membuat batasan UNIQUE, indeks nonclustered unik dibuat untuk menegakkan batasan UNIQUE secara default.
Anda bisa menentukan Indeks Clustered UNIK jika Indeks Clustered belum ada untuk tabel.
Ini berarti bahwa pertanyaan Anda tentang Indeks Berkelompok dan Kunci Utama sebenarnya tentang beberapa masalah berikut. Harap dicatat bahwa tidak setiap tabel mendapat manfaat dari paket pengindeksan yang sama.
Kapan saya akan mendapat manfaat dari Kunci Utama yang terpisah dari Indeks Berkelompok?
Mungkin ketika Indeks Clustered adalah Lebar (misalnya, 5 kolom informasi tekstual, tetapi Kunci Utama kecil (INT atau BIGINT), seperti yang tampaknya Anda gambarkan.
Haruskah Anda membuat Kunci Utama saja menjadi Indeks Berkelompok?
Jika Anda memiliki Kunci Utama kecil (INT atau BIGINT) dan itu adalah Indeks Clustered, overhead kolom cluster relatif kecil. Meskipun Kunci Utama Clustered dalam kasus ini juga akan ada di setiap indeks pada tabel ini, itu adalah harga yang lebih kecil untuk dibayar daripada Wide Cluster yang dibahas di atas.
Indeks Klaster Kunci Utama ini biasanya tidak secara langsung menawarkan jalur mudah untuk memilih banyak baris secara serial.
Sekarang Anda telah membuat Kunci Utama Clustered, bagaimana dengan kolom-kolom lain yang pernah Anda rencanakan untuk dimasukkan dalam Indeks Clustered ?
Buat indeks Unik (atau Non-Unik) sesuai kebutuhan untuk mengindeks kriteria pencarian luas kolom C1, C2, C3, C4, C5. Nilai-nilai dalam Indeks "Imitasi Berkelompok" ini dapat berfungsi sebagai jalur pencarian yang lebih cepat untuk 5 kolom tersebut. Jika ada satu atau dua kolom yang tidak diindeks yang secara teratur dipilih juga, mereka dapat dimasukkan dalam indeks dengan
INCLUDE (Doctor_Name, Diagnosis_Synopsis)
.Meskipun saya menemukan Indeks Clustered sederhana dan Kunci Utama berguna, ada beberapa alasan bagus untuk memikirkan apakah akan menggunakannya dalam tabel atau dalam database.
Apakah Anda memerlukan Indeks Clustered sama sekali?
Jika Anda membuat indeks (Indeks Unik dan Indeks Non-Unik) dan mendefinisikan Kunci Utama tanpa overhead menjadi Indeks Clustered, Anda mungkin menemukan bahwa indeks yang lebih sempit menyediakan apa yang Anda butuhkan untuk pertanyaan Anda.
Ada beberapa perilaku bermanfaat dalam Indeks Berkelompok dan Kunci Utama, tetapi ingat bahwa sebenarnya indekslah yang paling penting. Rancang strategi pengindeksan untuk memperhitungkan realitas aplikasi Anda. Mungkin
OneBigTable
kebutuhan untuk memiliki strategi pengindeksan yang berbeda dari apa yang Anda gunakan untuk sebagian besar tabel.Tanpa Indeks Clustered data Anda akan disimpan sebagai tumpukan dengan Row Identifier (RID) yang sama sekali bukan mekanisme pencarian yang baik. Tetapi, seperti yang disebutkan sebelumnya, Anda dapat membuat indeks yang unik dan tidak unik untuk menangani pertanyaan Anda.
Yang sekarang membuat Anda mempertimbangkan Heaps:
Tumpukan dan Indeks: https://msdn.microsoft.com/en-us/library/hh213609.aspx
Tetapi jika Anda juga memiliki beberapa 'hot spot' dalam kumpulan data besar, Anda juga dapat melihat jenis indeks lain:
Indeks yang Difilter: https://msdn.microsoft.com/en-us/library/cc280372.aspx
Indeks berfilter yang dirancang dengan baik meningkatkan kinerja kueri dan kualitas rencana eksekusi karena lebih kecil dari indeks tabel tidak tercakup penuh dan telah memfilter statistik. Statistik yang difilter lebih akurat daripada statistik tabel penuh karena hanya mencakup baris dalam indeks yang difilter .
Indeks yang difilter memiliki sejumlah batasan yang diuraikan dalam tautan ke indeks yang difilter.
Namun, jika Anda tertarik untuk memikirkan kemungkinan melewatkan Kunci Utama dan Indeks Berkelompok secara keseluruhan, Anda dapat membaca pos Markus Winand yang ditautkan di bawah ini. Dia mendemonstrasikan alasannya, dengan beberapa contoh kode, untuk menyarankan bahwa mungkin merupakan ide yang bagus untuk tidak menggunakan fitur-fitur tersebut.
http://use-the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key
Namun semuanya akhirnya kembali untuk memahami aplikasi Anda dan mendesain kode, tabel, indeks, dan sebagainya agar sesuai dengan pekerjaan yang Anda lakukan.
sumber
Beberapa hal yang perlu dipertimbangkan.
Sementara indeks (berkerumun atau tidak) pada nilai yang meningkat secara monoton menghemat halaman Anda terbelah selama sisipan massa, itu menciptakan titik panas baru di ujung akhir indeks. Meskipun ini mungkin bukan masalah dengan penyisipan utas tunggal, ia pasti akan meningkatkan pertikaian untuk aplikasi multithreaded yang memasukkan tupel baru dengan kecepatan tinggi, karena utas akan terus-menerus bersaing untuk mendapatkan akses ke halaman terakhir indeks.
Mengelompokkan tabel berdasarkan pengganti (identitas) PK jarang bermanfaat. Kunci primer semacam itu sebagian besar digunakan untuk mengakses tupel individual, satu per satu, atau memindai seluruh indeks untuk bergabung. Dalam kedua kasus itu tidak masalah apakah indeks berkerumun atau tidak (dengan pengecualian gabungan bergabung, mungkin, tetapi seberapa sering mereka?)
Saya pikir Anda akan mendapat manfaat paling banyak dari indeks berkerumun yang mencakup kueri yang meminta pemindaian rentang kunci dan predikat tambahan yang merujuk kolom lain.
sumber