GUID berurutan atau bigint untuk tabel database 'besar' PK

14

Saya tahu jenis pertanyaan ini banyak muncul, tetapi saya belum membaca argumen yang meyakinkan untuk membantu saya membuat keputusan ini. Tolong bersamaku!

Saya memiliki database besar - itu tumbuh sekitar 10.000.000 catatan per hari. Data bersifat relasional, dan untuk alasan kinerja saya memuat tabel dengan BULK COPY. Untuk alasan ini, saya perlu membuat kunci untuk baris, dan tidak dapat mengandalkan kolom IDENTITAS.

Bilangan bulat 64-bit - bigint - cukup lebar untuk saya gunakan, tetapi untuk menjamin keunikan, saya membutuhkan generator terpusat untuk membuat ID saya untuk saya. Saat ini saya memiliki layanan generator yang memungkinkan layanan untuk memesan nomor urut X dan tidak menjamin tabrakan. Namun, konsekuensi dari ini adalah bahwa semua layanan yang saya miliki bergantung pada generator terpusat yang satu ini, dan jadi saya terbatas dalam bagaimana saya dapat mendistribusikan sistem saya dan tidak senang dengan dependensi lain (seperti membutuhkan akses jaringan) yang dikenakan oleh desain ini. Ini merupakan masalah pada kesempatan tertentu.

Saya sekarang mempertimbangkan untuk menggunakan GUID berurutan sebagai kunci utama saya (dihasilkan secara eksternal ke SQL). Sejauh yang saya dapat memastikan dari pengujian saya sendiri, satu-satunya kelemahan untuk ini adalah ruang disk overhead dari tipe data yang lebih luas (yang diperburuk oleh penggunaannya dalam indeks). Saya belum melihat adanya pelemahan yang terlihat dalam kinerja kueri, dibandingkan dengan alternatif bigint. Memuat tabel dengan BULK COPY sedikit lebih lambat, tetapi tidak terlalu banyak. Indeks berbasis GUID saya tidak menjadi terfragmentasi berkat implementasi GUID berurutan saya.

Pada dasarnya, yang ingin saya ketahui adalah jika ada pertimbangan lain yang mungkin saya abaikan. Saat ini, saya cenderung untuk melakukan lompatan dan mulai menggunakan GUID. Saya sama sekali bukan pakar basis data, jadi saya sangat menghargai panduan apa pun.

Barguast
sumber
2
Bagaimana Anda menghasilkan "GUID berurutan"?
Ini implementasi kustom. Ini pada dasarnya format tipe GUID yang memiliki 6 byte diganti dengan timestamp byte, dan 2 byte yang mewakili nomor urut di mana stempel waktu yang sama. Ini tidak dijamin untuk menghasilkan nilai sekuensial yang sempurna, tetapi cukup baik untuk membuat fragmentasi indeks menjadi non-masalah bagi saya.
Apakah karena itu Anda memuat data ini dari berbagai sumber yang berbeda? Saya juga berasumsi bahwa indeks yang Anda khawatirkan terpecah-pecah adalah indeks yang dikelompokkan?
2
Jika Anda menggunakan GUID berurutan, Anda harus melihat NEWSEQUENTIALID (). Ini harus melakukan apa yang Anda inginkan (meningkat secara monoton), dan tidak bergantung pada kode khusus.
2
Lihatlah posting Jeremiah Peschka pada Masalah dengan kunci. Bacalah yang baik dan dia berkali-kali berurusan dengan implementasi ini.
billinkc

Jawaban:

4

Saya dalam situasi yang sama. Saat ini, saya menggunakan pendekatan GUID berurutan dan tidak memiliki fragmentasi dan pembuatan kunci yang mudah.

Saya perhatikan dua disadavantage yang menyebabkan saya mulai bermigrasi ke bigint:

  1. Penggunaan ruang . 8 byte lebih banyak per indeks. Lipat gandakan dengan 10 indeks atau lebih dan Anda akan membuang banyak ruang.
  2. Indeks Columnstore tidak mendukung GUID.

(2) Apakah pembunuhnya bagi saya.

Sekarang saya akan menghasilkan kunci saya seperti ini:

yyMMddHH1234567890

Saya akan menggunakan tanggal plus jam terkemuka dan memiliki bagian berurutan setelah itu. Itu memungkinkan saya untuk melakukan range-query data saya berdasarkan tanggal tanpa indeks tambahan sama sekali. Ini bonus bagus untukku.

Saya akan menghasilkan bagian berurutan dari bigint menggunakan algoritma HiLo yang cocok untuk didistribusikan .

Semoga beberapa transfer ini ke situasi Anda. Saya merekomendasikan penggunaan bigint.

usr
sumber
1
Menandai ini sebagai 'jawaban', karena itu yang paling cocok (dan Anda tampaknya menghargai apa yang saya tanyakan dan mengapa ini tidak semudah yang pertama kali muncul). Saya pikir saya akan pergi dengan generator urutan bersama (yang akan bekerja mirip dengan saran algoritma HiLo Anda). Saya memiliki ini bekerja pada sistem lain dengan beberapa masalah, saya hanya harus tahan dengan ketergantungan ekstra. Baiklah. Terima kasih.
Barguast
3

Dengan tipe INT, mulai dari 1, Anda mendapatkan lebih dari 2 miliar baris yang mungkin - yang seharusnya lebih dari cukup untuk sebagian besar kasus. Dengan BIGINT, Anda mendapatkan sekitar 922 kuadriliun (922 dengan 15 nol - 922'000 miliar) - cukup untuk Anda ??

Jika Anda menggunakan INT IDENTITYawal pada 1, dan Anda memasukkan baris setiap detik, Anda perlu 66,5 tahun sebelum Anda mencapai batas 2 miliar ....

Jika Anda menggunakan BIGINT IDENTITYawal pada 1, dan Anda memasukkan seribu baris setiap detik, Anda memerlukan 292 juta tahun yang mencengangkan sebelum Anda mencapai batas 922 kuadriliun ....

Dengan menggunakan 10 juta baris per hari, itu akan membuat Anda memiliki angka yang cukup untuk sekitar 1'844'674'407'370 hari ( 1844 miliar hari atau lebih dari 5 miliar tahun ) data - apakah itu cukup baik untuk kebutuhan Anda ?

Baca lebih lanjut tentang itu (dengan semua opsi ada) di MSDN Books Online .

marc_s
sumber
1
Tingkat penyisipan 10 juta baris per hari akan menghabiskan rentang INT dalam 200 hari.
mceda
@ Mceda: Ya - apakah saya mengklaim hal lain? Itu tidak menguras BIGINTrentang secepat itu, ....
marc_s
Terima kasih, tetapi seperti yang saya katakan di pertanyaan saya, saya perlu ID sebelum dikirim ke database. Data bersifat relasional, jadi saya perlu menetapkan kunci primer dan asing sebelum disalin secara massal. Jika bukan karena itu, IDENTITAS BIGINT mungkin akan sempurna.
2
@ Barguast: tidak bisakah Anda hanya menyisipkan data secara massal ke tabel pementasan (tanpa identitas) dan kemudian memindahkannya dari sana ke dalam tabel data aktual menggunakan BIGINT IDENTITY?
marc_s
@marc_s: ya, perhitungan yang diberikan tidak selaras dengan pertanyaan: "Jika Anda menggunakan IDENTITAS INT mulai dari 1, dan Anda memasukkan baris setiap detik, Anda perlu 66,5 tahun sebelum mencapai batas 2 miliar".
mceda
2

Saya sarankan Anda menggunakan SEQUENCE tipe data BIGINT di SQL 2012 Ini jauh lebih fleksibel daripada IDENTITAS dengan opsi seperti cache / nocache, Anda juga dapat menetapkan rentang urutan untuk operasi batch Anda sebagai sp_afterence_get_range.


sumber
Sayangnya, URUTAN tidak didukung di Sql Azure.
Timothy Lee Russell
2

Apakah alasan Anda tidak dapat menggunakan IDENTITAS karena sudah ada hubungan kunci asing antara tabel terpisah yang Anda muat? Dan tidak ada kunci alami lain bagi Anda untuk dapat menghubungkan mereka dalam operasi dari area pementasan ke area produksi? Untuk alasan itu, saya ingin tahu lebih banyak tentang bagaimana mereka saat ini "ditautkan" dalam sistem sumber sebelum Anda menyalin secara massal? Apakah beberapa sistem sumber hanya menggunakan urutan mereka sendiri dan memiliki kemungkinan untuk urutan yang bertentangan ketika dibawa ke database bersama?

Teknik COMB ID / urutan GUID adalah salah satu yang saya kenal, dan itu bisa diterapkan kapan saja Anda secara efektif membutuhkan keunikan global yang ditugaskan di luar database - itu secara efektif identitas baris yang dapat digunakan baik di dalam maupun di luar database. Untuk alasan itu, dalam lingkungan yang sangat terdistribusi atau skenario yang terputus, itu adalah pilihan yang OK

Kecuali jika Anda benar-benar tidak membutuhkannya, Karena perbedaan lebar ekstra itu penting ketika ukuran data tumbuh dan kunci-kunci ini ada di setiap indeks dan set kerja untuk banyak pertanyaan.

Juga, dengan generasi didistribusikan, jika baris tidak benar-benar datang dalam urutan kolom GUID, masalah dengan menggunakan ini untuk kunci indeks berkerumun (sempit, statis, meningkat) berpotensi menyebabkan beberapa fragmentasi dibandingkan dengan pengelompokan pada IDENTITAS masih tetap.

Cade Roux
sumber
0

Secara umum dimungkinkan untuk menggunakan OUTPUTklausa INSERTperintah untuk memasukkan data ke dalam tabel dan terkait dengan bidang identitas.

Identifier yang didasarkan pada stempel waktu tidak boleh dianggap andal - itu tergantung pada jam sistem yang pada gilirannya tergantung pada banyak hal - dari jam perangkat keras ke layanan sinkronisasi waktu.

Serg
sumber