Tipe data uuid
yang sempurna cocok untuk tugas. Ini hanya menempati 16 byte sebagai lawan dari 37 byte di RAM untuk representasi varchar
atau text
. (Atau 33 byte pada disk, tetapi angka ganjil akan membutuhkan padding dalam banyak kasus untuk membuatnya 40 byte secara efektif.) Dan uuid
tipe ini memiliki beberapa kelebihan.
Contoh:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Detail dan penjelasan lebih lanjut:
Anda mungkin mempertimbangkan fungsi hashing lainnya (lebih murah) jika Anda tidak memerlukan komponen kriptografi dari md5, tapi saya akan menggunakan md5 untuk use case Anda (kebanyakan hanya baca-saja).
Sebuah kata peringatan : Untuk kasus Anda ( immutable once written
) a fungsional tergantung (pseudo-alam) PK baik-baik saja. Tetapi hal yang sama akan menyusahkan jika pembaruan text
dimungkinkan. Pikirkan untuk memperbaiki kesalahan ketik: PK dan semua indeks tergantung, kolom FK di dozens of other tables
dan referensi lainnya harus berubah juga. Tabel dan indeks mengasapi, masalah penguncian, pembaruan lambat, referensi hilang, ...
Jika text
dapat berubah dalam operasi normal, PK pengganti akan menjadi pilihan yang lebih baik. Saya menyarankan sebuah bigserial
kolom (kisaran -9223372036854775808 to +9223372036854775807
- itu sembilan trilyun dua ratus dua puluh tiga kuadriliun tiga ratus tujuh puluh dua triliun tiga puluh enam sesuatu miliar ) nilai yang berbeda untuk billions of rows
. Mungkin ide yang baik dalam setiap kasus: 8 bukan 16 ! Byte untuk puluhan kolom FK dan indeks). Atau UUID acak untuk kardinalitas yang jauh lebih besar atau sistem terdistribusi. Anda selalu dapat menyimpan kata md5 (as uuid
) tambahan untuk menemukan baris di tabel utama dari teks asli dengan cepat. Terkait:
Adapun permintaan Anda :
Untuk mengatasi komentar @ Daniel : Jika Anda lebih suka representasi tanpa tanda hubung, hapus tanda hubung untuk ditampilkan:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Tapi aku tidak mau repot. Representasi default baik-baik saja. Dan masalahnya bukan representasi di sini.
Jika pihak lain harus memiliki pendekatan yang berbeda dan melempar string tanpa tanda hubung ke dalam campuran, itu tidak masalah juga. Postgres menerima beberapa representasi teks yang masuk akal sebagai input untuk a uuid
. Dokumentasi :
PostgreSQL juga menerima formulir alternatif berikut untuk input: penggunaan digit huruf besar, format standar yang dikelilingi oleh kawat gigi, menghilangkan beberapa atau semua tanda hubung, menambahkan tanda hubung setelah grup yang terdiri dari empat digit. Contohnya adalah:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Apa lagi, md5()
kembali fungsi text
, Anda akan menggunakan decode()
untuk mengkonversi ke bytea
dan representasi default yang adalah:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Anda harus encode()
kembali untuk mendapatkan representasi teks asli:
SELECT encode(my_md5_as_bytea, 'hex');
Sebagai tambahan, nilai yang disimpan bytea
akan menempati 20 byte dalam RAM (dan 17 byte pada disk, 24 dengan padding ) karena overhead internalvarlena
, yang sangat tidak menguntungkan untuk ukuran dan kinerja indeks sederhana.
Semuanya berfungsi mendukung di uuid
sini.
text
kolom juga - bahkan jika itu bukan "teks" sama sekali.SELECT encode(decode('tZmffOd5Tbh8yXaVlZfRJQ==', 'base64'), 'hex')::uuid;
.uuid
adalah tipe 16-byte yang tidak dapat menyimpan hasil dari algoritma SHA yang menghasilkan antara 160 dan 512 bit. Tidak ada tipe serupa yang sesuai dengan distribusi standar Postgres. Anda dapat membuat satu ... Gagal itu, default kebytea
- seperti pg_crypto tidak.Saya akan menyimpan MD5 dalam kolom
text
atau avarchar
. Tidak ada perbedaan kinerja antara berbagai tipe data karakter. Anda mungkin ingin membatasi panjang nilai md5 dengan menggunakanvarchar(xxx)
untuk memastikan nilai md5 tidak pernah melebihi panjang tertentu.Daftar IN besar biasanya tidak terlalu cepat, lebih baik melakukan sesuatu seperti ini:
Opsi lain yang kadang-kadang dikatakan lebih cepat adalah menggunakan array:
Karena Anda hanya membandingkan untuk kesetaraan, indeks BTree biasa harus baik-baik saja. Kedua pertanyaan harus dapat menggunakan indeks seperti itu (terutama jika mereka hanya memilih sebagian kecil dari baris.
sumber
bit
tipe itu jadi saya tidak bisa mengomentari itu. Mengingat jumlah baris yang Anda harapkan, saran Erwin tampaknya lebih baik karena penghematan ruang yang Anda dapatkan dengan menyimpan ini sebagai UUIDOpsi lain adalah menggunakan 4 INTEGER atau 2 kolom BIGINT.
sumber