Pertanyaannya bukan 'kapan PK harus NC', tetapi Anda harus bertanya 'apa kunci yang tepat untuk indeks berkerumun'?
Dan jawabannya sangat tergantung pada bagaimana Anda meminta data . Indeks berkerumun memiliki keunggulan dibandingkan semua indeks lain: karena selalu mencakup semua kolom, selalu mencakup. Oleh karena itu pertanyaan yang dapat memanfaatkan indeks berkerumun tentu tidak perlu menggunakan pencarian untuk memenuhi beberapa kolom yang diproyeksikan dan / atau predikat.
Bagian lain dari teka-teki adalah bagaimana indeks dapat digunakan ? Ada tiga pola khas:
- probe, ketika nilai kunci tunggal dicari dalam indeks
- rentang pemindaian, ketika rentang nilai kunci diambil
- memesan dengan persyaratan, ketika indeks dapat memenuhi pesanan dengan w / o membutuhkan semacam stop-and-go
Jadi, jika Anda menganalisis beban yang diharapkan (kueri) dan menemukan bahwa sejumlah besar kueri akan menggunakan indeks tertentu karena mereka menggunakan pola akses tertentu yang diuntungkan dari indeks, masuk akal untuk mengajukan indeks itu sebagai indeks berkerumun.
Namun faktor lain adalah bahwa kunci indeks berkerumun adalah kunci pencarian yang digunakan oleh semua indeks yang tidak berkerumun dan karena itu kunci indeks berkerumun luas menciptakan efek riak dan memperluas semua indeks yang tidak berkerumun dan indeks lebar berarti lebih banyak halaman, lebih banyak I / O , lebih banyak memori, lebih sedikit kebaikan.
Indeks berkerumun yang baik stabil , itu tidak berubah selama masa entitas, karena perubahan nilai kunci indeks berkerumun berarti baris harus dihapus dan dimasukkan kembali.
Dan indeks berkerumun yang baik tumbuh agar tidak secara acak (setiap nilai kunci yang baru dimasukkan lebih besar dari nilai sebelumnya) untuk menghindari pemisahan halaman dan fragmentasi (tanpa bermain-main dengan FILLFACTOR
s).
Jadi sekarang kita tahu apa kunci indeks berkerumun yang baik, apakah kunci utama (yang merupakan properti logis pemodelan data) cocok dengan persyaratan? Jika ya, maka PK harus dikelompokkan. Jika tidak, maka PK harus non-cluster.
Untuk memberikan contoh, pertimbangkan tabel fakta penjualan. Setiap entri memiliki ID yang merupakan kunci utama. Tetapi sebagian besar pertanyaan meminta data antara tanggal dan tanggal lain, oleh karena itu kunci indeks terkluster terbaik adalah tanggal penjualan , bukan ID . Contoh lain dari memiliki indeks pengelompokan berbeda dari kunci primer adalah kunci selektivitas yang sangat rendah, seperti 'kategori', atau 'keadaan', kunci dengan hanya beberapa nilai berbeda. Memiliki kunci indeks berkerumun dengan kunci selektivitas rendah ini sebagai kunci paling kiri, misalnya (state, id)
, sering masuk akal karena pemindaian rentang yang mencari semua entri dalam 'keadaan' tertentu.
Satu catatan terakhir tentang kemungkinan kunci primer non-cluster di atas heap (yaitu tidak ada indeks cluster sama sekali). Ini mungkin skenario yang valid, alasan khasnya adalah ketika kinerja penyisipan massal sangat penting, karena tumpukan memiliki throughput penyisipan massal yang jauh lebih baik bila dibandingkan dengan indeks yang dikelompokkan.
(state, id)
. Dalam contoh ini, "indeks cluster yang baik tumbuh agar tidak secara acak" persyaratan tidak akan dipenuhi, bukan? Jadi bisakah kita menganggapnya sebagai indeks berkerumun yang baik?Alasan dasar untuk menggunakan indeks Clustered dinyatakan di Wikipedia :
Katakan bahwa saya memiliki tabel Orang, dan orang-orang ini memiliki kolom Negara dan Kunci Utama yang unik. Ini adalah tabel demografi, jadi ini adalah satu-satunya hal yang saya pedulikan; Negara apa dan berapa banyak orang unik yang terikat pada negara itu.
Dengan demikian, saya hanya akan cenderung untuk MEMILIH DIMANA atau MEMESAN OLEH kolom Negara; indeks berkerumun pada Kunci Utama tidak ada gunanya bagiku, aku tidak mengakses data ini dengan PK, aku mengaksesnya dengan kolom lain ini. Karena saya hanya dapat memiliki satu indeks berkerumun di atas meja, menyatakan PK saya sebagai Berkelompok akan mencegah saya menggunakan Indeks Berkelompok di Negara.
Selain itu, inilah artikel yang bagus tentang Indeks Clustered vs Nonclustered , ternyata indeks clustered menyebabkan masalah kinerja penyisipan di SQL Server 6.5 (yang setidaknya semoga tidak relevan bagi kebanyakan dari kita di sini).
Perhatikan bahwa ini tidak terjadi di versi yang lebih baru.
sumber
Jika kunci utama Anda dari
UNIQUEIDENTIFIER
, pastikan untuk menentukan bahwa ituNONCLUSTERED
. Jika Anda membuatnya berkerumun, setiap sisipan harus melakukan banyak pengocokan catatan untuk menyisipkan baris baru di posisi yang benar. Ini akan menurunkan kinerja.sumber
UNIQUEIDENTIFIER
Tipe berurutan juga ada, dan memiliki probabilitas yang sama untuk menghasilkan kunci unik, meskipun masih memiliki ukuran 128.Contoh yang sangat umum:
Customer
meja denganCustomerID
asCLUSTERED PRIMARY KEY
OrderID (PK), CustomerID, OrderDate
dan beberapa kolom lainnyaOrderPositions
denganOrderPositionID (PK), OrderId, ProductID, Amount, Price ...
Tentu saja "itu tergantung" adalah - seperti hampir selalu - jawaban yang benar, tetapi sebagian besar aplikasi (bukan BI-Laporan) akan berfungsi berdasarkan pelanggan (misalnya Anda login sebagai pelanggan 278 ke situs web dan klik ke "Pesanan saya" atau Petugas mendaftar semua pesanan untuk pelanggan 4569 atau rutin faktur Anda akan meringkas semua pesanan untuk pelanggan 137).
Dalam hal ini tidak masuk akal untuk mengelompokkan tabel dengan
OrderID
. Ya, Anda akan memiliki pertanyaan tentangSELECT ... WHERE OrderId = ?
daftar detail pesanan, tetapi biasanya indeks ini pendek dan murah (3 kali dibaca).Di sisi lain, jika Anda akan mengelompokkan
Order
tabel Anda denganCustomerID
, itu tidak harus melakukan pencarian kunci ganda setiap kali Anda meminta tabel untukCustomerId = ?
.The
CLUSTERED INDEX
harus selaluUNIQUE
, jika SQL Server akan menambahkan (= tidak dapat digunakan) kolom INT tak terlihatUNIQUIFIER
untuk memastikan uniquiness - dan itu akan lebih masuk akal untuk menambahkan nyata data (digunakan) kemudian beberapa acak (tergantung pada urutan Memasukkan) hal.Karena pelanggan akan (semoga) melakukan lebih dari satu pesanan, kami harus menambahkan salah satu
OrderID
atau (jika Anda mengurutkan untuk ini) theOrderDate
(jika ini adalah waktu - - jika pelanggan akan dibatasi untuk satu pesanan per hari) untuk yangCLUSTERED INDEX
dan berakhir dengan:CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)
Aturan yang sama berlaku untuk
OrderPositions
tabel. Biasanya pertanyaan paling banyak akan mencantumkan semua posisi untuk pada urutan tertentu, jadi Anda harus membuat PK denganOrderPositionID
asNONCLUSTERED
danUNIQUE CLUSTERED INDEX
onOrderId, OrderPositionID
.BTW: benar bahwa
Customer
tabel dikelompokkan oleh PK-nya (CustomerID
karena, itu adalah "Top-Level-Table" dan akan - dalam aplikasi yang khas - sebagian besar dipertanyakan oleh CustomerID-nya.Tabel lookup murni seperti misalnya
Genders
atauInvoiceTypes
atauPaymentType
adalah contoh lain dari tabel yang harus dikelompokkan dengan PK-nya (karena Anda biasanya akan bergabung dengannyaGenderId
,InvoiceTypeId
atauPaymentTypeId
).sumber
Ketika indeks berkerumun dianggap lebih bermanfaat bagi sistem keseluruhan daripada PK berkerumun dengan menggunakan beberapa ukuran kinerja. Hanya ada satu indeks berkerumun di atas meja.
Contoh ukuran kinerja adalah waktu kueri tunggal (kecepatan), integrasi waktu kueri total terhadap tabel (efisiensi) dan harus menambahkan banyak kolom termasuk ke indeks non-cluster yang sangat besar untuk mencapai kinerja yang mirip dengan clustered (ukuran ).
Ini dapat terjadi ketika data umumnya diambil menggunakan indeks yang tidak unik, berisi nulls (tidak diizinkan dalam PK), atau PK ditambahkan untuk alasan sekunder (seperti replikasi atau identifikasi catatan jejak audit).
sumber