2014-10-10 78 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