Saya baru-baru ini mewarisi database SQL Server yang menggunakan BINARY(16)
alih-alih UNIQUEIDENTIFIER
untuk menyimpan Guids. Ini melakukan ini untuk semuanya termasuk kunci utama.
Haruskah saya khawatir?
sql-server
migration
uuid
Jonathan Allen
sumber
sumber
Jawaban:
Nah, ada beberapa hal di sini yang sedikit memprihatinkan.
Pertama: sementara benar bahwa
UNIQUEIDENTIFIER
(yaituGuid
) adalah nilai biner 16-byte, juga benar bahwa:INT
Dapat disimpanBINARY(4)
,DATETIME
dapat disimpanBINARY(8)
, dll), karenanya # 2 ↴sysname
sebagai alias untukNVARCHAR(128)
).Tiga perbedaan perilaku yang dapat saya temukan adalah:
Membandingkan
UNIQUEIDENTIFIER
nilai dalam SQL Server, baik atau buruk, sebenarnya tidak dilakukan dengan cara yang sama seperti membandingkanBINARY(16)
nilai. Menurut halaman MSDN untuk Membandingkan GUID dan Uniqueidentifier Values , ketika membandingkanUNIQUEIDENTIFIER
nilai dalam SQL Server:Meskipun nilai-nilai ini tidak sering diurutkan, ada sedikit perbedaan antara kedua jenis ini. Menurut halaman MSDN untuk pengidentifikasi unik :
Mengingat bahwa ada perbedaan dalam bagaimana nilai-nilai GUID ditangani antara SQL Server dan .NET (dicatat dalam halaman "Membandingkan GUID dan Uniqueidentifier Values" yang ditautkan di atas), menarik data ini dari SQL Server ke kode aplikasi mungkin tidak ditangani dengan benar di kode aplikasi jika perlu meniru perilaku perbandingan SQL Server. Perilaku itu dapat ditiru dengan mengonversi ke
SqlGuid
, tetapi apakah pengembang tahu untuk melakukan itu?Kedua: berdasarkan pernyataan berikut
Saya akan prihatin secara umum untuk kinerja sistem dengan menggunakan GUID sebagai PK alih-alih sebagai Kunci Alternatif bersamaan dengan menggunakan
INT
atau bahkanBIGINT
sebagai PK. Dan bahkan lebih khawatir jika PK GUID ini adalah Indeks Clustered.MEMPERBARUI
Komentar berikut, yang dibuat oleh OP pada jawaban @ Rob, memunculkan keprihatinan tambahan:
GUID dapat disimpan dalam 2 format biner yang berbeda . Jadi, mungkin ada alasan untuk khawatir tergantung pada:
Masalah dengan di mana representasi biner dihasilkan berkaitan dengan pemesanan byte dari 3 pertama dari 4 "bidang". Jika Anda mengikuti tautan di atas ke artikel Wikipedia, Anda akan melihat bahwa RFC 4122 menentukan untuk menggunakan pengkodean "Big Endian" untuk semua 4 bidang, namun Microsoft GUID menentukan dengan menggunakan Endianness "Asli". Yah, arsitektur Intel adalah Little Endian, maka urutan byte untuk 3 bidang pertama dibalik dari sistem mengikuti RFC (serta GUID gaya Microsoft yang dihasilkan pada sistem Big Endian). Bidang pertama, "Data 1", adalah 4 byte. Dalam satu Endianness itu akan direpresentasikan sebagai (secara hipotesis)
0x01020304
. Tetapi di Endianness lain itu akan menjadi0x04030201
. Jadi jika database saat ini 'BINARY(16)
bahwa representasi biner dihasilkan pada sistem yang mengikuti RFC, lalu mengonversi data yang saat ini ada di dalamBINARY(16)
bidangUNIQUEIDENTIFIER
akan menghasilkan GUID yang berbeda dari yang awalnya dibuat. Ini tidak benar-benar menimbulkan masalah JIKA nilai-nilai tidak pernah meninggalkan database, dan nilai-nilai hanya pernah dibandingkan untuk kesetaraan dan bukan pemesanan.Kekhawatiran dengan pemesanan hanya karena mereka tidak akan berada dalam urutan yang sama setelah mengonversi
UNIQUEIDENTIFIER
. Untungnya, jika sistem asli benar-benar MySQL maka pemesanan tidak pernah dilakukan pada representasi biner karena MySQL hanya memiliki string representasi UUID .Kekhawatiran dengan nilai string yang digunakan di luar database lebih serius, sekali lagi, jika representasi biner dihasilkan di luar Windows / SQL Server. Karena pemesanan byte berpotensi berbeda, maka GUID yang sama dalam bentuk string akan menghasilkan 2 representasi biner yang berbeda, tergantung di mana konversi itu terjadi. Jika kode aplikasi atau pelanggan diberi GUID dalam bentuk string yang
ABC
berasal dari bentuk biner123
dan representasi biner dihasilkan pada sistem yang mengikuti RFC, maka representasi biner yang sama (yaitu123
) akan menerjemahkan ke bentuk stringDEF
ketika dikonversi ke aUNIQUEIDENTIFIER
. Demikian juga, bentuk string asliABC
akan dikonversi ke bentuk biner456
saat dikonversi ke aUNIQUEIDENTIFIER
.Jadi, jika GUID tidak pernah meninggalkan database maka tidak ada yang perlu dikhawatirkan di luar pemesanan. Atau, jika impor dari MySQL dilakukan dengan mengonversi bentuk string (yaitu
FCCEC3D8-22A0-4C8A-BF35-EC18227C9F40
) maka mungkin ok. Selain itu, jika GUID itu diberikan kepada pelanggan atau dalam kode aplikasi, Anda dapat menguji untuk melihat bagaimana mereka mengonversi dengan mendapatkannya dan mengonversi melaluiSELECT CONVERT(UNIQUEIDENTIFIER, 'value found outside of the database');
dan melihat apakah Anda menemukan catatan yang diharapkan. Jika Anda tidak dapat mencocokkan catatan maka Anda mungkin harus menjaga bidang sebagaiBINARY(16)
.Kemungkinan besar tidak akan ada masalah, tetapi saya menyebutkan ini karena dalam kondisi yang tepat mungkin ada masalah.
Dan bagaimana pula GUID baru bisa dimasukkan? Dihasilkan dalam kode aplikasi?
PEMBARUAN 2
Jika penjelasan sebelumnya tentang masalah potensial terkait dengan mengimpor representasi biner dari GUID yang dihasilkan pada sistem lain sedikit (atau banyak) membingungkan, mudah-mudahan hal berikut akan sedikit lebih jelas:
Dalam output yang ditunjukkan di atas, nilai "String" dan "Binary" berasal dari GUID yang sama. Nilai di bawah garis "Binary" adalah nilai yang sama dengan baris "Binary", tetapi diformat dalam gaya yang sama dengan garis "String" (yaitu dihapus "0x" dan menambahkan empat garis). Membandingkan nilai pertama dan ketiga, mereka tidak persis sama, tetapi mereka sangat dekat: paling kanan dua bagian identik, tetapi paling kiri tiga bagian tidak. Tetapi jika Anda melihat lebih dekat, Anda dapat melihat bahwa itu adalah byte yang sama di masing-masing dari tiga bagian, hanya dalam urutan yang berbeda. Mungkin lebih mudah untuk melihat apakah saya hanya menampilkan tiga bagian pertama, dan memberi nomor byte sehingga lebih mudah untuk melihat bagaimana urutannya berbeda antara dua representasi:
String = 1 5F 2 ED 3 23 4 BE - 5 E5 6 2C - 7 40 8 EE
Binary = 4 BE 3 23 2 ED 1 5F - 6 2C 5 E5 - 8 EE 7 40 (di Windows / SQL Server)
Jadi dalam setiap pengelompokan, urutan byte dibalik, tetapi hanya di Windows dan juga SQL Server. Namun, pada sistem yang mematuhi RFC, representasi biner akan mencerminkan representasi sengatan karena tidak akan ada pembalikan urutan byte.
Bagaimana data dibawa ke SQL Server dari MySQL? Berikut ini beberapa pilihan:
Pengembalian:
Dengan asumsi itu adalah biner langsung ke biner (yaitu Konversi # 2 di atas), maka GUID yang dihasilkan, jika dikonversi menjadi aktual
UNIQUEIDENTIFIER
, akan menjadi:Pengembalian:
Yang salah. Dan itu meninggalkan kita dengan tiga pertanyaan:
sumber
Anda selalu bisa khawatir. ;)
Sistem mungkin telah dimigrasikan dari beberapa sistem lain yang tidak mendukung pengidentifikasi unik. Apakah ada kompromi lain yang tidak Anda ketahui?
Perancang mungkin tidak tahu tentang tipe pengenal unik. Hal-hal apa lagi yang tidak mereka ketahui?
Namun secara teknis - itu seharusnya tidak menjadi perhatian utama.
sumber