Các kiểu dữ liệu uuid
là hoàn toàn phù hợp với nhiệm vụ. Nó chỉ chiếm 16 byte so với 37 byte trong RAM cho varchar
hoặc text
đại diện. (Hoặc 33 byte trên đĩa, nhưng số lẻ sẽ yêu cầu đệm trong nhiều trường hợp để tạo ra nó 40 byte hiệu quả.) Và uuid
loại này có một số lợi thế hơn.
Thí dụ:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Chi tiết và giải thích thêm:
Bạn có thể xem xét các hàm băm khác (rẻ hơn) nếu bạn không cần thành phần mật mã của md5, nhưng tôi sẽ sử dụng md5 cho trường hợp sử dụng của bạn (chủ yếu là chỉ đọc).
Một lời cảnh báo : Đối với trường hợp của bạn ( immutable once written
) một PK phụ thuộc chức năng (giả tự nhiên) là tốt. Nhưng điều tương tự sẽ là một nỗi đau nơi cập nhật text
là có thể. Hãy nghĩ đến việc sửa lỗi chính tả: PK và tất cả các chỉ mục phụ thuộc, các cột FK dozens of other tables
và các tham chiếu khác cũng sẽ phải thay đổi. Sự phình to của bảng và chỉ mục, sự cố khóa, cập nhật chậm, tài liệu tham khảo bị mất, ...
Nếu text
có thể thay đổi trong hoạt động bình thường, PK thay thế sẽ là lựa chọn tốt hơn. Tôi đề nghị một bigserial
cột (phạm vi -9223372036854775808 to +9223372036854775807
- đó là chín triệu hai trăm hai mươi ba triệu ba trăm bảy mươi hai nghìn tỷ ba mươi sáu tỷ tỷ ) giá trị khác biệt cho billions of rows
. Có thể là một ý tưởng tốt trong mọi trường hợp: 8 thay vì 16 byte cho hàng chục cột và chỉ mục FK!). Hoặc một UUID ngẫu nhiên cho các hồng y hoặc hệ thống phân tán lớn hơn nhiều . Bạn luôn có thể lưu trữ md5 (as uuid
) nói thêm để tìm các hàng trong bảng chính từ văn bản gốc một cách nhanh chóng. Liên quan:
Đối với truy vấn của bạn :
Để giải quyết nhận xét của @ Daniel : Nếu bạn thích một đại diện không có dấu gạch ngang, hãy xóa dấu gạch nối để hiển thị:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Nhưng tôi sẽ không làm phiền. Các đại diện mặc định là tốt. Và vấn đề thực sự không phải là đại diện ở đây.
Nếu các bên khác nên có một cách tiếp cận khác và ném các chuỗi không có dấu gạch nối vào hỗn hợp, thì đó cũng không phải là vấn đề. Postgres chấp nhận một số biểu diễn văn bản hợp lý làm đầu vào cho a uuid
. Tài liệu :
PostgreSQL cũng chấp nhận các hình thức thay thế sau đây cho đầu vào: sử dụng chữ số viết hoa, định dạng chuẩn được bao quanh bởi dấu ngoặc, bỏ qua một số hoặc tất cả dấu gạch nối, thêm dấu gạch nối sau bất kỳ nhóm bốn chữ số nào. Ví dụ là:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Hơn nữa, md5()
hàm trả về text
, bạn sẽ sử dụng decode()
để chuyển đổi thànhbytea
và đại diện mặc định của đó là:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Bạn sẽ phải encode()
một lần nữa để có được đại diện văn bản gốc:
SELECT encode(my_md5_as_bytea, 'hex');
Trên hết, các giá trị được lưu trữ bytea
sẽ chiếm 20 byte trong RAM (và 17 byte trên đĩa, 24 với phần đệm ) do chi phí nội bộvarlena
, đặc biệt bất lợi cho kích thước và hiệu suất của các chỉ mục đơn giản.
Tất cả mọi thứ hoạt động có lợi cho một uuid
ở đây.