我有一个MySQL表,包含:
CREATE TABLE `url_list` (
`id` int(10) unsigned NOT NULL auto_increment,
`crc32` int(10) unsigned NOT NULL,
`url` varchar(512) NOT NULL,
PRIMARY KEY (`id`),
KEY `crc32` (`crc32`)
);
当将数据插入到相关表中时,我需要从该表中查找主键,使用crc32在允许小索引的情况下确实加快了速度。url确实需要是唯一的,但我希望避免索引多于实际数据。
如果该值不存在,我需要插入它,但是使用
INSERT IGNORE
或DUPLICATE KEY
之类的结构,要么需要在巨大的varchar上放置unique,要么不利用我的索引。如何“选择id else INSERT”,同时保持表中80-90%点击率的查找速度?
最佳答案
我建议取消id
列和crc32
列,因为它们不是必需的。
您可以使用MD5()
哈希来提供固定长度的值,实际上是从冗长的URL数据中计算出的唯一值,然后使用该哈希作为主键。
CREATE TABLE `url_list` (
`url_hash` BINARY(16) NOT NULL PRIMARY KEY
`url` VARCHAR(512) NOT NULL
);
DELIM !!
CREATE TRIGGER `url_ins` BEFORE INSERT ON `url_list`
FOR EACH ROW
BEGIN
SET NEW.`url_hash` = UNHEX( MD5( NEW.`url` ) );
END!!
然后可以使用
INSERT..ON DUPLICATE KEY UPDATE
,因为与crc32
不同,散列的冲突几率应该很低。编辑:请参见http://en.wikipedia.org/wiki/Birthday_attack。如果你在2000年里每天记录100万个不同的URL,那么这些URL的MD5散列仍然不太可能包含冲突,而你的硬盘可能会出现无法纠正的位错误。