MySQL高效“select id else insert”查询

时间:2008-11-25 15:49:11

标签: performance mysql

我有一个包含以下内容的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或ON DUPLICATE KEY等结构要么我要在巨大的varchar上放一个唯一的,或者不要利用我的索引。

如何“SELECT id else INSERT”,同时保留表中已有80-90%命中的查找速度?

2 个答案:

答案 0 :(得分:3)

我建议放弃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哈希值仍然不太可能包含冲突,而不是硬盘具有无法纠正的位错误。

答案 1 :(得分:1)

This website为类似问题提供了解决方案。