Saya memiliki aplikasi yang membuat jutaan tabel dalam database SQL Server 2008 (non clustered). Saya mencari untuk meng-upgrade ke SQL Server 2014 (berkerumun), tetapi saya menekan pesan kesalahan ketika sedang dimuat:
"Sudah ada objek bernama 'PK__tablenameprefix__179E2ED8F259C33B' dalam database"
Ini adalah nama kendala yang dihasilkan sistem. Sepertinya nomor 64-bit yang dihasilkan secara acak. Mungkinkah saya melihat tabrakan karena banyaknya tabel? Dengan asumsi saya memiliki 100 juta tabel, saya menghitung kemungkinan tabrakan kurang dari 1 dalam 1 triliun ketika menambahkan tabel berikutnya, tetapi itu mengasumsikan distribusi yang seragam. Apakah mungkin bahwa SQL Server mengubah algoritma pembuatan nama antara versi 2008 dan 2014 untuk meningkatkan kemungkinan tabrakan?
Perbedaan signifikan lainnya adalah bahwa instance 2014 saya adalah pasangan berkerumun, tetapi saya berjuang untuk membentuk hipotesis mengapa itu akan menghasilkan kesalahan di atas.
PS Ya, saya tahu membuat jutaan tabel itu gila. Ini adalah kode pihak ke-3 kotak hitam yang tidak dapat saya kendalikan. Meskipun kegilaan, itu bekerja di versi 2008 dan sekarang tidak di versi 2014.
Sunting: pada pemeriksaan lebih dekat, akhiran yang dihasilkan sepertinya selalu dimulai dengan 179E2ED8 - yang berarti bagian acak sebenarnya hanya nomor 32-bit dan kemungkinan tabrakan hanya 1-in-50 setiap kali tabel baru ditambahkan, yang adalah pertandingan yang jauh lebih dekat dengan tingkat kesalahan yang saya lihat!
Jawaban:
Ini tergantung pada jenis batasan dan versi SQL Server.
Contoh Hasil 2008
Contoh Hasil 2017
Untuk batasan default, periksa batasan dan batasan kunci asing, 4 byte terakhir dari nama yang dihasilkan secara otomatis adalah versi hexadecimal dari objectid dari kendala. Seperti
objectid
yang dijamin unik namanya juga harus unik. Di Sybase juga menggunakan initabname_colname_objectid
Untuk batasan unik dan batasan kunci primer yang digunakan Sybase
Ini juga akan menjamin keunikan.
SQL Server tidak menggunakan skema ini.
Dalam SQL Server 2008 dan 2017 menggunakan string 8 byte pada akhir nama sistem yang dihasilkan namun algoritma telah berubah tentang bagaimana 4 byte terakhir yang dihasilkan.
Pada tahun 2008, 4 byte terakhir mewakili penghitung bilangan bulat yang ditandatangani yang diimbangi
object_id
oleh-16000057
dengan nilai negatif apa pun yang membungkus hingga maksimum yang ditandatangani. (Signifikansi16000057
adalah bahwa ini adalah kenaikan yang diterapkan antara yang dibuat secara berturut-turutobject_id
). Ini masih menjamin keunikan.Pada 2012 ke atas saya tidak melihat pola sama sekali antara object_id dari kendala dan integer yang diperoleh dengan memperlakukan 8 karakter terakhir dari nama sebagai representasi heksadesimal dari int yang ditandatangani.
Nama-nama fungsi di tumpukan panggilan pada 2017 menunjukkan bahwa itu sekarang membuat GUID sebagai bagian dari proses pembuatan nama (Pada 2008 saya tidak melihat menyebutkan
MDConstraintNameGenerator
). Saya kira ini untuk memberikan beberapa sumber keacakan. Jelas itu tidak menggunakan keseluruhan 16 byte dari GUID dalam 4 byte yang mengubah kendala.Saya kira algoritma baru dilakukan untuk beberapa alasan efisiensi dengan mengorbankan beberapa kemungkinan peningkatan tabrakan dalam kasus-kasus ekstrim seperti milik Anda.
Ini adalah kasus yang cukup patologis karena memerlukan awalan nama tabel dan nama kolom PK (sejauh ini mempengaruhi 8 karakter sebelum 8 akhir) untuk identik untuk puluhan ribu tabel sebelum menjadi kemungkinan tetapi dapat direproduksi cukup dengan mudah dengan di bawah ini.
Contoh berjalan pada SQL Server 2017 terhadap database yang baru dibuat gagal hanya dalam satu menit (setelah 50.931 tabel dibuat)
sumber
Ingat ini adalah " masalah ulang tahun ". Anda tidak mencoba untuk menghasilkan collision untuk hash tunggal, tetapi mengukur probabilitas bahwa tidak satu pun dari banyak pasangan nilai yang akan bertabrakan.
Jadi dengan N tabel, ada N * (N-1) / 2 pasang, jadi di sini sekitar 10 16 pasang. Jika probabilitas tabrakan adalah 2 -64 , probabilitas satu pasangan tidak bertabrakan adalah 1-2 -64 , tetapi dengan begitu banyak pasangan, kemungkinan tidak ada tabrakan di sini adalah sekitar (1-2 -64 ) 10 16 , atau lebih seperti 1 / 10.000. Lihat misalnya https://preshing.com/20110504/hash-collision-probabilities/
Dan jika itu hanya hash 32bit kemungkinan tabrakan melintasi 1/2 hanya pada nilai 77k.
sumber