Pertimbangan Utama
Saya melihat satu keuntungan penting untuk tumpukan dan satu untuk tabel berkerumun, ditambah pertimbangan ketiga yang bisa berjalan baik.
Tumpukan menghemat lapisan tipuan. Indeks berisi ID baris, menunjuk langsung (well, tidak benar-benar, tetapi selurus mungkin) ke lokasi disk. Dengan demikian, pencarian indeks terhadap tumpukan harus biaya sekitar setengah indeks pencarian non-cluster terhadap tabel berkerumun.
Indeks berkerumun diurutkan, per se, berkat indeks (hampir) gratis. Karena indeks pengelompokan tercermin dalam urutan fisik data, maka dibutuhkan ruang yang relatif sedikit di atas data aktual itu sendiri, yang tentu saja Anda harus tetap menyimpannya. Karena dipesan secara fisik, pemindaian rentang terhadap indeks ini dapat mencari ke titik awal dan kemudian zip bersama ke titik akhir dengan sangat efisien.
Indeks pada tumpukan referensi RID, yang 64 bit. Seperti disebutkan, indeks yang tidak berkerumun di tabel berkerumun merujuk kunci pengelompokan, yang bisa lebih kecil (32-bit INT
), sama (64-bit BIGINT
), atau lebih besar (48-bit DATETIME2()
plus 32-bit INT
, atau GUID 128-bit). Jelas referensi yang lebih luas membuat indeks lebih besar dan lebih mahal.
Persyaratan Ruang
Dengan dua tabel ini:
CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)
CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)
... masing-masing diisi dengan catatan 8,7 M, ruang yang dibutuhkan adalah 150 MB untuk data untuk keduanya; 120 MB untuk indeks tabel berkerumun, 310 MB untuk indeks tabel tidak berkerumun. Ini mencerminkan bahwa indeks cluster lebih sempit daripada RID, dan bahwa indeks clustering kebanyakan adalah "freebie." Tanpa indeks unik aktif ID2
, ruang indeks yang dibutuhkan turun hingga 155 MB untuk tabel non-cluster (setengah, seperti yang Anda harapkan) tetapi hanya 150 KB untuk PK cluster - hampir tidak ada.
Jadi indeks non-clustered dari bidang 32-bit dalam tabel clustered dengan indeks 32-bit (total 64 bit, nominal) mengambil 120 MB, sedangkan indeks bidang 32-bit di heap dengan 64-bit RID (total 96 bit, nominal) mengambil 155 MB, sedikit kurang dari peningkatan 50% yang secara naif diharapkan akan beralih dari kunci 64-bit ke 96-bit, tetapi tentu saja ada overhead yang mengurangi perbedaan ukuran yang efektif.
Mengisi dua tabel dan membuat indeks mereka mengambil jumlah waktu yang sama untuk setiap tabel. Menjalankan tes sederhana yang melibatkan pemindaian atau pencarian, saya tidak menemukan perbedaan kinerja material di antara tabel, yang cocok dengan kertas putih Microsoft yang terkait dengan gbn. Makalah tersebut memang menunjukkan perbedaan yang signifikan untuk akses yang sangat bersamaan; Saya tidak yakin mengapa itu terjadi, semoga seseorang dengan pengalaman lebih banyak daripada saya dengan sistem OLTP volume tinggi dapat memberi tahu kami.
Menambahkan ~ 40 byte data panjang variabel acak tidak cukup mengubah kesetaraan ini. Mengganti INT
s dengan UUID lebar juga tidak (masing-masing tabel diperlambat dengan tingkat yang sama). Jarak tempuh Anda mungkin bervariasi, tetapi dalam kebanyakan kasus apakah indeks tersedia lebih penting daripada jenis apa.
Potongan-potongan
Melakukan pemindaian rentang terhadap indeks yang tidak berkerumun - baik karena tabelnya adalah tumpukan atau indeks bukan indeks berkerumun - melibatkan pemindaian indeks dan kemudian melakukan pencarian terhadap tabel untuk setiap klik. Ini bisa sangat mahal, jadi kadang-kadang lebih murah hanya memindai tabel. Anda dapat mengatasinya dengan indeks penutup. Ini berlaku apakah Anda telah mengelompokkan meja Anda atau tidak.
Seperti yang ditunjukkan @gbn, tidak ada cara sederhana untuk memadatkan tumpukan. Namun, jika meja Anda meningkat secara bertahap seiring waktu - kasus yang sangat umum - akan ada sedikit pemborosan karena ruang yang dibebaskan oleh penghapusan akan diisi oleh data baru.
Beberapa diskusi tabel tumpukan vs berkerumun yang saya lihat membuat argumen strawman yang penasaran bahwa tumpukan tanpa indeks lebih rendah daripada tabel berkerumun karena selalu membutuhkan pemindaian tabel. Ini memang benar, tetapi perbandingan yang lebih bermakna adalah "tabel berkerumun besar yang diindeks dengan baik" vs. Jika meja Anda sangat kecil atau Anda selalu akan melakukan pemindaian tabel, maka tidak masalah jika Anda mengelompokkannya atau tidak.
Karena setiap indeks dalam tabel berkerumun referensi indeks pengelompokan, mereka berlaku semua indeks yang meliputi. Kueri yang mereferensikan kolom yang diindeks dan kolom pengelompokan dapat melakukan pemindaian indeks tanpa pencarian tabel. Ini umumnya tidak berharga jika indeks pengelompokan Anda adalah kunci sintetis, tetapi jika itu adalah kunci bisnis yang harus Anda ambil kembali, itu adalah fitur yang bagus.
TL; DR
Saya seorang pria data warehousing, bukan ahli OLTP. Untuk tabel fakta saya hampir selalu menggunakan indeks pengelompokan pada bidang yang sebagian besar kemungkinan membutuhkan pemindaian rentang, biasanya bidang tanggal. Untuk tabel dimensi, saya mengelompokkan pada PK sehingga didaftar untuk menggabungkan bergabung dengan tabel fakta.
Ada beberapa alasan untuk menggunakan indeks pengelompokan, tetapi jika tidak ada alasan yang berlaku maka overhead mungkin tidak bermanfaat. Saya menduga ada banyak "kami selalu melakukannya dengan cara ini" dan "itu hanya praktik terbaik" di belakang orang yang menggunakan indeks berkerumun secara universal. Cobalah kedua dengan Anda data dan Anda beban dan melihat apa yang terbaik.