我有一个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 IGNOREDUPLICATE 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散列仍然不太可能包含冲突,而你的硬盘可能会出现无法纠正的位错误。

10-07 19:12
查看更多