2014-10-10 96 views
0

我想知道如果我可以优化它更多,也许有人与此挣扎。MySQL InnoDB哈希索引优化

首先我有表:

CREATE TABLE `site_url` (
    `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `url_hash` CHAR(32) NULL DEFAULT NULL, 
    `url` VARCHAR(2048) NULL DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    INDEX `url_hash` (`url_hash`) 
) 
ENGINE=InnoDB; 

,我的商店网站URI(域是在不同的表,但对这个问题的id的目的并不重要 - 我希望)

url_hash MD5是从url

计算的似乎所有的字段都是很好的长度,索引应该是正确的,但有一些数据在里面,我正在寻找更多的优化。

标准查询看起来是这样的:

select id from site_url where site_url.url_hash = MD5('something - often calculated in application rather than in mysql') and site_url.url = 'something - often calculated in application rather than in mysql' 

描述给出:

+----+-------------+----------+------+---------------+----------+---------+-------+------+------------------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows |    Extra    | 
+----+-------------+----------+------+---------------+----------+---------+-------+------+------------------------------------+ 
| 1 | SIMPLE  | site_url | ref | url_hash  | url_hash |  97 | const | 1 | Using index condition; Using where | 
+----+-------------+----------+------+---------------+----------+---------+-------+------+------------------------------------+ 

但我知道如果我能帮助的MySQL这样做搜索。它必须通过InnoDB引擎,因为它的长度,我不能添加到url的密钥

我的朋友告诉我把hash缩短为16个字符,并将其写为数字。 BIGINT上的索引将快于char(32)吗?朋友还建议做MD5,并采取16首/最后一个字符,但我认为这会造成更多的碰撞。

您对此有何看法?

+1

可以缩短'url_hash'到'二进制(16)'。一个整数不会大到可以将散列存储为数字。这应该给你更多的空间。而且,优化MySQL将会非常有帮助。查看你的'innodb_buffer_pool_size'变量和谷歌周围,看看人们在做什么来增强MySQL的性能。 – 2014-10-10 08:10:29

+0

这是一个好主意,在重构过程中处理的问题较少。只需要改变2个查询和现场:INSERT'insert到SITE_URL(url_hash,URL)值(UNHEX(MD5( '/ URI')), '/ URI');'然后选择:'SELECT ID FROM SITE_URL USE INDEX( url_hash)WHERE url_hash = UNHEX(MD5( '/ URI'))和URL = '/ URI';' – 2014-10-10 08:46:14

+0

没错,也有你知道MySQL使用UNHEX是呼吸新鲜空气,说实话:)不如果你还没有的话,忘记优化InnoDB。 – 2014-10-10 09:15:41

回答

1

这是您的查询:

select id 
from site_url 
where site_url.url_hash = MD5('something - often calculated in application rather than in mysql') and 
     site_url.url = 'something - often calculated in application rather than in mysql'; 

此查询的最好的指标将是对site_url(url_hash, url, id)。需要注意的是,除非您设置了较大的前缀选项,否则您可能需要使用前缀(请参见innodb_large_prefix)。

+0

感谢您的回复目前我不知道如果我可以更改innodb_large_prefix变量,您的索引似乎是最好的,直到您可以创建这样一个长索引 – 2014-10-10 07:59:55

0

如果url_hash是url的md5,为什么你用2个键选择?

select id from site_url where site_url.url_hash = MD5('something - often calculated in application rather than in mysql'); 

其实你不需要检查site_url.url;

但是,如果你愿意,你可以通过2场与USE INDEX语法选择:

select id from site_url USE INDEX (url_hash) where site_url.url_hash = MD5('something - often calculated in application rather than in mysql') and site_url.url = 'something - often calculated in application rather than in mysql'); 
+0

我使用2个字段在哪里可以肯定我没有碰撞在MD5哈希(相同的哈希,但不同的网址) – 2014-10-10 07:50:42

+0

嗯。如果您对md5不确定,请使用带有256个字符的sha2。 – 2014-10-10 07:53:01

+0

我有一个类似的项目与网址等。 md5和sha2适合我,没有碰撞。 – 2014-10-10 07:54:50