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 idbidang kenaikan-otomatis dan menggunakannya bersamaan dengan company_idsebagai 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 IDENTITYkolom ditambahkan atau apakah itu overhead yang tidak perlu?
Jika Anda menambahkan INT IDENTITYkolom 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 IDENTITYkolom, maka Anda tidak dapat membuat PK di tabel ini. Namun, Anda masih bisa membuat Indeks Berkelompok di atas meja selama Anda tidak menggunakan UNIQUEopsi. 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 IDkolom dalam kueri.
INT IDENTITY Kolom atau Kolom Hash of org_pathPersistent Computed?
Mengingat bahwa Anda tidak akan mencari baris berdasarkan org_pathnilai, 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 IDENTITYKolom "ID" mungkin yang terbaik.
Urutan Kolom Kunci
Mengingat bahwa IDKolom 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 FILLFACTOR90. 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_pathnilai-nilai dalam a company_idadalah unik, Anda masih harus membuat Trigger INSERT, UPDATEuntuk menegakkan ini. Di Trigger, lakukan IF EXISTSdengan kueri yang mungkin dilakukan a COUNT(*)dan GROUP BY company_id, org_path. Jika ada yang ditemukan, keluarkan a ROLLBACKuntuk membatalkan operasi DML dan RAISERRORpepatah 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 _BIN2Kolasi 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.