Satu hal yang perlu dipertimbangkan adalah bahwa Kunci Utama dan Indeks Berkelompok bukan hal yang sama. Kunci Utama adalah kendala dan berkaitan dengan aturan yang digunakan data tersebut (yaitu integritas data); tidak ada hubungannya dengan efisiensi / kinerja. Kunci Utama mengharuskan kolom kunci unik (dalam kombinasi) dan BUKAN NULL (satu per satu). PK diberlakukan melalui Indeks Unik, meskipun dapat berupa Clustered atau Non-Clustered.
A Clustered Index adalah sarana untuk secara fisik (yaitu pada disk) memesan data dalam tabel dan berhubungan dengan kinerja; tidak ada hubungannya dengan integritas data. Indeks Clustered bisamengharuskan kolom kunci unik (dalam kombinasi), tetapi tidak perlu. Namun, karena Indeks Clustered adalah urutan fisik data, itu perlu mengidentifikasi setiap baris secara unik apa pun yang terjadi. Jadi, jika Anda tidak mengaturnya untuk membutuhkan keunikan, itu akan membuat keunikannya sendiri melalui kolom "uniquifier" 4 byte yang tersembunyi. Kolom itu selalu ada di Non-Unique Clustered Indexes, tetapi tidak memakan ruang apa pun ketika bidang kunci unik (dalam kombinasi). Untuk melihat secara langsung bagaimana kolom "uniquifier" ini bekerja (baik dalam Clustered Index dan pengaruhnya terhadap Non-Clustered Indexes), silakan periksa skrip pengujian yang saya posting di PasteBin: T-SQL script untuk menguji ukuran Uniquifier .
Oleh karena itu, pertanyaan utama:
apakah akan lebih efisien untuk menambahkan id
bidang kenaikan-otomatis dan menggunakannya bersamaan dengan company_id
sebagai kunci utama, atau apakah akan menambah overhead yang tidak perlu
adalah menggabungkan kedua konsep itu, sehingga mereka perlu ditangani secara terpisah, meskipun pasti ada beberapa tumpang tindih.
Haruskah IDENTITY
kolom ditambahkan atau apakah itu overhead yang tidak perlu?
Jika Anda menambahkan INT IDENTITY
kolom dan menggunakannya untuk membuat PK, dengan asumsi itu akan menjadi PK Clustered, yang menambahkan 4 byte ke setiap baris. Kolom ini terlihat dan dapat digunakan dalam kueri. Itu bisa ditambahkan ke tabel lain sebagai Kunci Asing, meskipun dalam kasus khusus ini tidak akan terjadi.
Jika Anda tidak menambahkan INT IDENTITY
kolom, maka Anda tidak dapat membuat PK di tabel ini. Namun, Anda masih bisa membuat Indeks Berkelompok di atas meja selama Anda tidak menggunakan UNIQUE
opsi. Dalam hal ini, SQL Server akan menambahkan kolom tersembunyi yang disebut "uniquifier" yang berperilaku seperti dijelaskan di atas. Karena kolom disembunyikan, itu tidak dapat digunakan dalam permintaan atau sebagai referensi untuk Kunci Asing.
Sejauh efisiensi berjalan, opsi-opsi ini kira-kira sama. Ya, akan ada sedikit lebih sedikit ruang yang diambil dengan memiliki Non-Unique Clustered Index karena beberapa baris (yang dengan nilai kunci unik awal) mengambil 0 byte sementara semua baris di IDENTITY
/ PK akan mengambil 4 byte. Tetapi tidak akan ada cukup baris 0 byte (terutama dengan jumlah baris kecil yang diharapkan) untuk melihat perbedaan, apalagi menimbang kenyamanan untuk dapat menggunakan ID
kolom dalam kueri.
INT IDENTITY Kolom atau Kolom Hash of org_path
Persistent Computed?
Mengingat bahwa Anda tidak akan mencari baris berdasarkan org_path
nilai, maka tidak masuk akal untuk menambahkan overhead Kolom yang Dikomputasi Persisten ditambah perlu menghitung hash dalam kueri untuk mencocokkan dengan Kolom yang Dihitung (ini adalah milik saya saran asli, tersedia dalam riwayat revisi di sini , yang didasarkan pada kata-kata awal / rincian Pertanyaan). Dalam kasus khusus ini, INT IDENTITY
Kolom "ID" mungkin yang terbaik.
Urutan Kolom Kunci
Mengingat bahwa ID
Kolom akan jarang, jika pernah, digunakan dalam permintaan, dan mengingat bahwa dua kasus penggunaan utama adalah untuk mendapatkan "semua baris" atau "semua baris untuk suatu pemberian company_id
", saya akan membuat PK aktif company_id, id
. Dan karena ini berarti bahwa baris tidak dimasukkan secara berurutan, saya akan menentukan nilai FILLFACTOR
90. Anda juga perlu memastikan untuk melakukan pemeliharaan indeks secara teratur untuk mengurangi fragmentasi.
Pertanyaan kedua
apakah fakta bahwa company_id adalah kunci utama dalam tabel lain berpengaruh di sini
Tidak.
Pelatuk
Karena org_path
nilai-nilai dalam a company_id
adalah unik, Anda masih harus membuat Trigger INSERT, UPDATE
untuk menegakkan ini. Di Trigger, lakukan IF EXISTS
dengan kueri yang mungkin dilakukan a COUNT(*)
dan GROUP BY company_id, org_path
. Jika ada yang ditemukan, keluarkan a ROLLBACK
untuk membatalkan operasi DML dan RAISERROR
pepatah yang mengatakan ada duplikat.
Pemeriksaan
Dalam jawaban awal saya (berdasarkan perincian kata-kata asli / jarang dari pertanyaan, dan tersedia dalam sejarah revisi di sini ), saya telah menyarankan kemungkinan menggunakan _BIN2
Kolasi biner (yaitu ). Sekarang kita memiliki wawasan tentang apa sebenarnya org_path
, saya tidak akan merekomendasikan menggunakan Kolasi biner. Karena akan ada tanda diakritik, Anda jangan ingin memanfaatkan ekuivalensi linguistik.
Mengapa Anda membutuhkan PK?
Mengapa tidak langsung menggunakan company_id sebagai indeks non-cluster?
Anda mengatakan bahwa yang paling dicari adalah pada semua entri atau oleh company_id
Jarang memperbarui
Jarang menghapus
org_path, ini adalah satu-satunya tabel di mana ada
Jawaban dari Martin Smith mungkin mendapatkan apa yang Anda butuhkan
Saya tidak akrab dengan secara otomatis menambahkan bilangan bulat 4 byte uniqueifier
Mungkin aku kehilangan sesuatu tapi jika Anda tidak memiliki kolom lain diindeks maka saya tidak melihat tujuan untuk itu dalam hal ini menggunakan
Jika Anda khawatir tentang DRI tabel harus menggunakan tabel Perusahaan sebagai FK untuk company_id
sumber
INCLUDE
kolom, tapi itu lebih buruk karena hanya menduplikasi tabel. Benar, PK tidak perlu; bagian penting adalah Indeks Clustered. Tapi begitu Anda memiliki IDENTITAS, mungkin juga pergi dengan PK. Dan tolong lihat tautan baru dalam jawaban saya untuk walk-through di Uniquifier 😃