2012-06-08 40 views
71

Dựa trên câu trả lời của câu hỏi, UUID performance in MySQL, người trả lời đề xuất lưu trữ UUID dưới dạng một số chứ không phải dưới dạng chuỗi. Tôi không chắc làm thế nào nó có thể được thực hiện. Bất cứ ai cũng có thể đề nghị tôi một cái gì đó? Làm thế nào mã ruby ​​của tôi đối phó với điều đó?Làm thế nào để lưu trữ uuid dưới dạng số?

+5

Sự cố hiệu suất chỉ phát sinh khi bạn đang sử dụng UUID là khóa chính, vì UUID không phải là khóa chính rất hiệu quả. Tại sao bạn cần UUID? Bạn có thể giữ UUID và chỉ sử dụng autoincrement làm khóa chính không? –

+3

@ThomSmith Re "UUID không phải là các khóa chính rất hiệu quả" .. cẩn thận để trích dẫn một nguồn giải thích tại sao? – Pacerier

+1

Đó là một phần dữ liệu lớn hơn và thường sẽ mất nhiều hướng dẫn hơn để so sánh. Nó không phải tuần tự, do đó chi phí lập chỉ mục cao hơn một chút. Và, tất nhiên, nếu bạn đang lưu trữ nó như là một chuỗi thay vì một số 128-bit, như OP dường như đang làm, tình hình tồi tệ hơn. Nó không phải là một chìa khóa khủng khiếp, nhưng tôi sẽ không sử dụng nó trừ khi có một số lý do bên ngoài để làm như vậy. –

Trả lời

99

Nếu tôi hiểu chính xác, bạn đang sử dụng UUID trong cột chính của mình? Mọi người sẽ nói rằng một khóa chính thường xuyên (nguyên) sẽ nhanh hơn, nhưng có một cách khác bằng cách sử dụng mặt tối của MySQL. Trong thực tế, MySQL nhanh hơn bằng cách sử dụng nhị phân hơn bất cứ điều gì khác khi chỉ mục được yêu cầu.

Vì UUID là 128 bit và được viết dưới dạng thập lục phân, rất dễ dàng để tăng tốc và lưu trữ UUID.

Thứ nhất, trong ngôn ngữ lập trình của bạn loại bỏ các dấu gạch ngang

Từ 110E8400-E29B-11D4-A716-446655440000-110E8400E29B11D4A716446655440000.

Bây giờ là 32 ký tự (giống như một băm MD5, điều này cũng hoạt động với).

Vì một đơn BINARY trong MySQL có kích thước 8 bit, BINARY(16) là kích thước của UUID (8 * 16 = 128).

Bạn có thể chèn sử dụng:

INSERT INTO Table (FieldBin) VALUES (UNHEX("110E8400E29B11D4A716446655440000"))

và truy vấn sử dụng:

SELECT HEX(FieldBin) AS FieldBin FROM Table

Bây giờ trong ngôn ngữ lập trình của bạn, lại chèn dấu gạch ngang tại các vị trí 9, 14, 19 và 24 để khớp với UUID ban đầu của bạn. Nếu các vị trí luôn khác nhau, bạn có thể lưu trữ thông tin đó trong trường thứ hai.

Full dụ:

CREATE TABLE `test_table` (
    `field_binary` BINARY(16) NULL , 
    PRIMARY KEY ( `field_binary`) 
) ENGINE = INNODB ; 

INSERT INTO `test_table` (
    `field_binary` 
) 
VALUES (
    UNHEX( '110E8400E29B11D4A716446655440000') 
); 

SELECT HEX(field_binary) AS field_binary FROM `test_table` 

Nếu bạn muốn sử dụng kỹ thuật này với bất kỳ chuỗi hex, luôn luôn làm length/2 cho chiều dài lĩnh vực. Vì vậy, đối với một sha512, trường sẽ là BINARY (64) vì mã hóa sha512 dài 128 ký tự.

+0

sử dụng chức năng unhex làm cho kết quả là con người không đọc được. Hàm – Chamnap

+0

@Chamnap UNHEX sẽ chuyển đổi HEX thành BINARY trong cơ sở dữ liệu của bạn. Sau đó bạn có thể sử dụng các chỉ mục trên nó mà không có vấn đề gì và với hiệu suất đạt được (có, có!). Sau đó bạn đọc dữ liệu với hàm 'HEX' như trong ví dụ của tôi. Vì vậy, không, bạn không thể đọc kết quả từ 'UNHEX', nhưng bạn có thể sử dụng' HEX'. Hãy nhớ rằng máy tính được làm bằng nhị phân, luôn luôn nhanh hơn. –

+3

@Chamnap Giả sử bạn có 10 000 hàng trong cơ sở dữ liệu của mình và chúng đã được thêm bằng hàm UNHEX và bạn muốn tìm kiếm UUID '110E8400-E29B-11D4-A716-446655440000'. Chỉ cần làm một cái gì đó như: 'SELECT * FROM test_table WHERE field_binary LIKE CONCAT ("% ", UNHEX ('110E8400E29B11D4A716446655440000'),"% ")' –

0

Tôi không nghĩ rằng nên sử dụng nhị phân.

Hãy nói rằng bạn muốn truy vấn một số giá trị:

SELECT HEX(field_binary) AS field_binary FROM `test_table` 

Nếu chúng ta đang quay trở lại nhiều giá trị thì chúng ta đang kêu gọi các chức năng HEX nhiều lần.

Tuy nhiên, vấn đề chính là tiếp theo một:

SELECT * FROM `test_table` 
    where field_binary=UNHEX('110E8400E29B11D4A716446655440000') 

Và sử dụng một chức năng bên trong đâu, chỉ đơn giản là bỏ qua các chỉ số.

Cũng

SELECT * FROM `test_table` 
    where field_binary=x'[email protected]#*#(&#@$9' 

Có thể dẫn đến nhiều vấn đề.

Các vấn đề liên quan