patternsqlModerate
MySQL: Unique constraint on large column
Viewed 0 times
uniquecolumnmysqllargeconstraint
Problem
I am trying to create an InnoDB table that contains a
MySQL appears to enforce constraints using an index. In InnoDB, index sizes appear to be limited to 767 bytes - not nearly enough for the
Any thoughts on how to have the database enforce uniqueness of the data, without compromising on maximum data length or the usage of InnoDB?
VARCHAR column that can hold up to 3071 characters. I would like to enforce a UNIQUE constraint on the data of this column.MySQL appears to enforce constraints using an index. In InnoDB, index sizes appear to be limited to 767 bytes - not nearly enough for the
VARCHAR(3071) column that is holding the data.Any thoughts on how to have the database enforce uniqueness of the data, without compromising on maximum data length or the usage of InnoDB?
Solution
You do not want a gigantic gen_clust_index (Internal Clustered Index). That size is ungodly huge even for a secondary index.
You may have to resort to triggers or stored procedures to check for the key well in advance.
You could also think about performing an SHA1 function call using the
Suppose you have this
and you want to make a
Then, count them
If the Counts are the Same, CONGRATULATIONS !!! Now you have a unique index of length 40. You can finish up with:
This could be more atomically as pointed out in the comments below:
Perform this on whatever table you intend to have this big column. You have to remember to add the SHA1 of the data along with the data upon
The odds of duplicate keys is 1 in 2 to the 160th power (that 1.4615016373309029182036848327163e+48. If I get the exact figure, I'll post it someday).
Give it a Try !!!
You may have to resort to triggers or stored procedures to check for the key well in advance.
You could also think about performing an SHA1 function call using the
VARCHAR(3071) field. SHA1 will return a 40-character field. This hash may be just what you need to index.Suppose you have this
CREATE TABLE mytable
(
id int not null auto_increment,
txt VARCHAR(3071),
primary key (id)
) ENGINE=InnODB;and you want to make a
UNIQUE index on txt. Try the SHA1 approachCREATE 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;Then, count them
SELECT COUNT(1) FROM mytable;
SELECT COUNT(1) FROM mytablenew;If the Counts are the Same, CONGRATULATIONS !!! Now you have a unique index of length 40. You can finish up with:
ALTER TABLE mytable RENAME mytableold;
ALTER TABLE mytablenew RENAME mytable;
DROP TABLE mytableold;This could be more atomically as pointed out in the comments below:
RENAME TABLE mytable TO mytableold, mytablenew TO mytable;
DROP TABLE mytableold;Perform this on whatever table you intend to have this big column. You have to remember to add the SHA1 of the data along with the data upon
INSERT.The odds of duplicate keys is 1 in 2 to the 160th power (that 1.4615016373309029182036848327163e+48. If I get the exact figure, I'll post it someday).
Give it a Try !!!
Code Snippets
CREATE TABLE mytable
(
id int not null auto_increment,
txt VARCHAR(3071),
primary key (id)
) ENGINE=InnODB;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;SELECT COUNT(1) FROM mytable;
SELECT COUNT(1) FROM mytablenew;ALTER TABLE mytable RENAME mytableold;
ALTER TABLE mytablenew RENAME mytable;
DROP TABLE mytableold;RENAME TABLE mytable TO mytableold, mytablenew TO mytable;
DROP TABLE mytableold;Context
StackExchange Database Administrators Q#27190, answer score: 11
Revisions (0)
No revisions yet.