MySQL: Ràng buộc duy nhất trên cột lớn


10

Tôi đang cố gắng tạo một bảng InnoDB có chứa một VARCHARcột có thể chứa tới 3071 ký tự. Tôi muốn thực thi một UNIQUEràng buộc về dữ liệu của cột này.

MySQL xuất hiện để thực thi các ràng buộc bằng cách sử dụng một chỉ mục. Trong InnoDB, kích thước chỉ mục dường như bị giới hạn ở 767 byte - gần như không đủ cho VARCHAR(3071)cột chứa dữ liệu.

Bạn có suy nghĩ gì về việc làm thế nào để cơ sở dữ liệu thực thi tính duy nhất của dữ liệu mà không ảnh hưởng đến độ dài dữ liệu tối đa hoặc việc sử dụng InnoDB không?

Câu trả lời:


10

Bạn không muốn có một gen_clust_index khổng lồ (Chỉ mục cụm nội bộ). Kích thước đó là vô cùng lớn ngay cả đối với một chỉ số phụ.

Bạn có thể phải dùng đến các kích hoạt hoặc các thủ tục được lưu trữ để kiểm tra khóa trước.

Bạn cũng có thể nghĩ về việc thực hiện cuộc gọi chức năng SHA1 bằng cách sử dụng VARCHAR(3071)trường. SHA1 sẽ trả về trường 40 ký tự. Băm này có thể chỉ là những gì bạn cần lập chỉ mục.

Giả sử bạn có cái này

CREATE TABLE mytable
(
    id int not null auto_increment,
    txt VARCHAR(3071),
    primary key (id)
) ENGINE=InnODB;

và bạn muốn tạo một UNIQUEchỉ mục trên txt. Hãy thử phương pháp SHA1

CREATE TABLE mytablenew LIKE mytable;
ALTER TABLE mytable ADD txtsha1 CHAR(40);
ALTER TABLE mytable ADD UNIQUE KEY (txtsha1);
INSERT INTO mytablenew (id,txt,txtsha1)
SELECT id,txt,SHA1(txt) FROM mytable;

Sau đó, đếm chúng

SELECT COUNT(1) FROM mytable;
SELECT COUNT(1) FROM mytablenew;

Nếu các Đếm giống nhau, HÃY THAM GIA !!! Bây giờ bạn có một chỉ mục duy nhất có độ dài 40. Bạn có thể kết thúc với:

ALTER TABLE mytable RENAME mytableold;
ALTER TABLE mytablenew RENAME mytable;
DROP TABLE mytableold;

Điều này có thể nguyên tử hơn như được chỉ ra trong các ý kiến ​​dưới đây:

RENAME TABLE mytable TO mytableold, mytablenew TO mytable;
DROP TABLE mytableold;

Thực hiện điều này trên bất cứ bảng nào bạn dự định có cột lớn này. Bạn phải nhớ thêm SHA1 của dữ liệu cùng với dữ liệu trên INSERT.

Tỷ lệ cược của các khóa trùng lặp là 1 trong 2 đến 160, (1.4615016373309029182036848327163e + 48. Nếu tôi nhận được con số chính xác, tôi sẽ đăng nó vào một ngày nào đó).

Hãy thử một lần !!!


+1 Về cơ bản, đây là một ý tưởng rất hay! Tôi sẽ kết hợp nó với một trình kích hoạt để kiểm tra xem hai bản tóm tắt có giống nhau không, nội dung cũng giống nhau, chính xác là cách HashMap trong Java hoạt động ...
ppeterka

1
Rolando - Tôi có nhiều điểm yếu: (1) sha1 nên là ascii, không phải utf8. (2) sha1 có thể là BINary (20) nếu bạn sử dụng HEX () và UNHEX (). (3) để thực hiện việc đổi tên nguyên tử, không có thời gian chết, hãy thực hiện RENAME TABLE mytable TO mytableold, mytablenew TO mytable. Sau đó DROP TABLE mytableold sau khi bạn hài lòng. (4) Tỷ lệ cược được trích dẫn là cho một hàng đơn. (5) 2 64 là sai - đó là 2 160. (6) tỷ lệ cược cho một bảng là: "Có một cơ hội trong 2 53 rằng một bảng có 2 53 hàng sẽ có một bản sao đôi." (6a) Bạn có nhiều khả năng nhận được một tiểu hành tinh trong khi thu thập trên xổ số siêu lớn.
Rick James

@RickJames tất cả các điểm lưu ý. Xin thứ lỗi toán học xấu của tôi cho điểm số 5, nó là 2 ^ 160. Tôi đã điều chỉnh số 3 trong câu trả lời của mình.
RolandoMySQLDBA

1
Các bạn, tỷ lệ cược bạn đưa ra giả định: 1. SHA có một bản phân phối hoàn hảo; và 2. đầu vào là hoàn toàn ngẫu nhiên. SHA không có phân phối hoàn hảo. Cũng không có bất kỳ thuật toán băm khác. Đầu vào không hoàn toàn ngẫu nhiên, và mặc dù SHA, như các tiêu hóa khác, gây ra những thay đổi lớn về đầu ra cho bất kỳ thay đổi nhỏ nào trong đầu vào, hoàn toàn có thể một số bộ đầu vào sẽ tạo ra cùng một đầu ra và những đầu vào đó có một số hệ thống kết nối giữa chúng. Bây giờ, tôi đang chủ yếu là lảm nhảm ở đây, vì tỷ lệ cược rất thấp; nhưng vẫn nên cảnh giác
Shlomi Noach

@ShlomiNoach phím băm có thể rất mạnh. Với tốc độ này, ngay cả chức năng PASSWORD cũng có thể được chấp nhận ( palominodb.com/blog/2011/12/04/hashing-alerskym-mysql-password )
RolandoMyQueryDBA
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.