Menggunakan GUID sebagai Kunci Primer

Saya biasanya menggunakan ID kenaikan otomatis sebagai Kunci Utama dalam database. Saya mencoba mempelajari manfaat menggunakan GUID. Saya telah membaca artikel ini: https://betterexplained.com/articles/the-quick-guide-to-guids/

Saya menyadari bahwa GUID ini digunakan untuk mengidentifikasi objek pada level aplikasi. Apakah GUID juga disimpan sebagai kunci utama di tingkat database. Sebagai contoh, katakanlah saya memiliki kelas berikut:

public class Person
{
public GUID ID;
public string Name;
..

//Person Methods follow
}

Katakanlah saya ingin membuat orang baru dalam memori dan kemudian memasukkan Orang tersebut ke dalam database. Dapatkah saya melakukan ini:

Person p1 = new Person();
p1.ID=GUID.NewGUID();
PersonRepository.Insert(p1);

Katakanlah saya memiliki database yang berisi jutaan dan jutaan baris dengan GUID sebagai Primary Key. Apakah ini akan selalu unik? Apakah saya bahkan memahami GUID dengan benar?

Saya membaca artikel ini sebelumnya: http://enterprisecraftsmanship.com/2014/11/15/cqs-with-database-generated-ids/. Artikel ini sedikit membingungkan saya karena tampaknya merekomendasikan media bahagia antara GUID dan bilangan bulat sebagai Kunci Utama.

Edit 11/06/18

Saya menjadi percaya bahwa GUID lebih cocok daripada int untuk kebutuhan saya. Saya lebih banyak menggunakan CQRS akhir-akhir ini dan GUID lebih cocok.

Saya perhatikan bahwa beberapa pengembang memodelkan GUID sebagai string dalam model domain, misalnya di sini: https://github.com/dotnet-architecture/eShopOnContainers/blob/dev/src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs - dalam hal ini: IdentityGuid adalah GUID yang dimodelkan sebagai string. Apakah ada alasan untuk melakukan hal ini selain dari apa yang dinyatakan di sini: https://softwareengineering.stackexchange.com/questions/239220/use-a-custom-value-object-or-a-guid-as-an-entity-identifier-in-a-distributed-sys. Apakah "normal &" untuk memodelkan GUID sebagai string atau haruskah saya memodelkannya sebagai GUID dalam model dan database?

GUID menurut definisi "Globally Unique IDentifiers". Ada konsep yang serupa tetapi sedikit berbeda di Java yang disebut UUID "Universally Unique IDentifiers ". Nama-nama tersebut dapat dipertukarkan untuk semua penggunaan praktis.

GUID adalah inti dari bagaimana Microsoft membayangkan pengelompokan database untuk bekerja, dan jika Anda perlu menggabungkan data dari sumber yang terkadang terhubung, GUID sangat membantu mencegah tabrakan data.

Beberapa Fakta Pro-GUID:

  • GUID mencegah tabrakan kunci
  • GUID membantu penggabungan data antar jaringan, mesin, dll.
  • SQL Server memiliki dukungan untuk GUID semi-urutan untuk membantu meminimalkan fragmentasi indeks (ref, beberapa peringatan)

Beberapa Kejanggalan dengan GUID

  • Mereka besar, masing-masing 16 byte
  • Mereka tidak berurutan, jadi Anda tidak dapat mengurutkan ID dan berharap untuk mendapatkan urutan penyisipan seperti yang Anda bisa pada id auto-increment
  • Mereka lebih rumit untuk digunakan, khususnya pada set data kecil (seperti tabel look up)
  • Implementasi GUID baru lebih kuat pada SQL Server daripada di library C# (Anda dapat memiliki GUID berurutan dari SQL Server, di C# itu acak)

GUID akan membuat indeks Anda lebih besar, sehingga biaya ruang disk untuk mengindeks kolom akan lebih tinggi. GUID acak akan memecah indeks Anda.

Jika Anda tahu Anda tidak akan menyinkronkan data dari jaringan yang berbeda, GUID dapat membawa lebih banyak overhead daripada nilainya.

Jika Anda memiliki kebutuhan untuk memasukkan data dari klien yang terkadang terhubung, GUID bisa jauh lebih kuat untuk mencegah tabrakan kunci daripada mengandalkan pengaturan rentang urutan untuk klien tersebut.

Komentar (23)

Apakah ini akan selalu unik?

Tidak, tidak selalu; ini adalah urutan bit yang terbatas.

Katakanlah saya memiliki database yang berisi jutaan baris dengan GUID sebagai Primary Key.

Jutaan dan jutaan, Anda mungkin aman. Satu juta juta, dan kemungkinan tabrakan menjadi signifikan. Namun, ada kabar baik: Anda sudah kehabisan ruang disk pada saat itu terjadi.

Bisakah saya melakukan ini?

Anda bisa; itu bukan ide yang sepenuhnya bagus. Model domain Anda seharusnya tidak menghasilkan angka acak; angka-angka tersebut seharusnya menjadi input untuk model Anda.

Di luar itu, ketika Anda berurusan dengan jaringan yang tidak dapat diandalkan, di mana Anda mungkin mendapatkan pesan duplikat, UUID yang dihasilkan secara deterministik akan melindungi Anda dari memiliki entitas duplikat. Tetapi jika Anda menetapkan nomor acak baru untuk masing-masing, maka Anda memiliki lebih banyak pekerjaan yang harus dilakukan untuk mengidentifikasi duplikasi.

Lihat deskripsi uuid berbasis nama di RFC 4122

Apakah normal untuk memodelkan GUID sebagai string atau haruskah saya memodelkannya sebagai GUID dalam model dan database?

Saya rasa itu tidak terlalu penting. Untuk sebagian besar model domain Anda, GUID adalah identifier; satu-satunya kueri yang Anda tanyakan adalah apakah GUID sama dengan beberapa pengenal lainnya atau tidak. Model domain Anda biasanya tidak akan melihat representasi memori dari sebuah pengenal.

Jika GUID tersedia sebagai "tipe primitif &" dalam pengaturan agnostik domain Anda, saya akan menggunakannya; ini memungkinkan konteks pendukung untuk memilih pengoptimalan yang sesuai yang mungkin tersedia.

Apa yang harus Anda kenali, bagaimanapun, adalah bahwa representasi pengenal, baik dalam memori maupun dalam penyimpanan, adalah keputusan yang Anda buat dalam implementasi Anda, dan oleh karena itu Anda harus mengambil langkah-langkah untuk memastikan bahwa jejak kode yang digabungkan dengan keputusan itu kecil - lihat Parnas 1972.

Komentar (8)

GUID atau UUID kemungkinan besar akan unik karena bagaimana mereka dihasilkan dan mereka menyediakan cara yang aman untuk menjamin keunikan tanpa harus berkomunikasi dengan otoritas pusat.

Manfaat GUID sebagai Kunci Utama:

  • Anda dapat menyalin data di antara pecahan cluster yang berbeda dan tidak perlu khawatir tentang tabrakan PK.
  • Memungkinkan Anda untuk mengetahui kunci utama Anda sebelum Anda memasukkan catatan apa pun.
  • Menyederhanakan logika transaksi untuk menyisipkan record anak.
  • Tidak dapat ditebak dengan mudah.

Dalam contoh yang Anda berikan:

Person p1 = new Person();
p1.ID = GUID.NewGUID();
PersonRepository.Insert(p1);

Menentukan GUID sebelum waktu penyisipan dapat menghemat perjalanan bolak-balik ke database saat menyisipkan catatan anak yang berurutan dan memungkinkan Anda untuk melakukan komit dalam transaksi yang sama.

Person p2 = new Person();
p2.ParentID = p1.ID
PersonRepository.Insert(p2);

Halangan untuk GUID sebagai Kunci Utama:

  • Ukurannya besar 16 byte yang berarti mereka akan mengkonsumsi lebih banyak ruang saat indeks dan kunci asing ditambahkan.
  • Mereka tidak mengurutkan dengan baik karena mereka pada dasarnya adalah angka acak.
  • Penggunaan indeks sangat, sangat, sangat buruk.
  • Banyak daun yang bergerak.
  • Mereka sulit untuk diingat.
  • Sulit untuk diucapkan.
  • Mereka dapat membuat URL sulit dibaca.

Jika aplikasi Anda tidak membutuhkan sharding atau clustering, akan lebih baik untuk tetap menggunakan tipe data yang lebih kecil dan sederhana seperti int atau bigint.

Banyak database memiliki implementasi internal mereka sendiri yang mencoba mengurangi masalah penyimpanan yang disebabkan oleh GUID's dan SQL Server bahkan memiliki fungsi newsequentialid untuk membantu pemesanan UUID's yang memungkinkan penggunaan indeks yang lebih baik dan mereka umumnya memiliki karakteristik kinerja yang lebih baik.

Selain itu, dari perspektif penguji, pengguna, atau pengembang yang bekerja dengan aplikasi, menggunakan ID daripada GUID akan meningkatkan komunikasi secara signifikan. Bayangkan harus membaca GUID melalui telepon.

Pada akhirnya, kecuali jika pengelompokan skala besar atau mengaburkan URL adalah persyaratan, lebih pragmatis untuk tetap menggunakan ID yang bertambah secara otomatis.

Komentar (11)