2009-09-08 61 views
1

我有一個大的MySQL InnoDB表(大約1百萬條記錄,每週增加300K)讓我們來說說博客文章。這個表格有一個帶有索引的url字段。在數據庫中使用MD5(URL)而不是URL用於WHERE

通過添加新記錄,我正在檢查具有相同網址的現有記錄。下面是查詢的樣子:

SELECT COUNT(*) FROM `tablename` WHERE url='http://www.google.com/'; 

當前系統每秒產生大約10-20個查詢,這個數量將會增加。我正在考慮通過添加URL的MD5散列的其他字段來提高性能。

SELECT COUNT(*) FROM `tablename` WHERE md5url=MD5('http://www.google.com/'); 

所以它會更短,並且具有恆定的長度,這對於索引來說比URL字段更好。你們對此有何想法?是否有意義?

我的朋友的另一個建議是使用CRC32而不是MD5,但我不確定CRC32的結果有多獨特。讓我知道你對這個角色的看法。

更新:URL列對每一行都是唯一的。

回答

4

在URL上創建一個非聚集索引。這將讓你的SQL引擎在內部完成所有的優化,並且會產生最好的結果!

如果您在VARCHAR列上創建索引,則SQL將在內部創建一個哈希值,並且使用索引可以將性能提高一個數量級甚至更多!

此外,東西要記住,如果你只是檢查URL是否存在,是某些SQL產品會產生更快的結果,像這樣的查詢:

IF NOT EXISTS(SELECT * FROM `tablename` WHERE url='') 
    -- return TRUE or do your logic here 
+1

我認爲「非羣集」是SQL Server的術語 - 不應該只是作爲索引讀取嗎? – 2009-09-08 17:12:18

+0

非聚集索引是數據上的「虛擬」索引,而聚簇索引是數據上的物理索引。每個表只能有一個聚簇索引,而在同一個表上可以有多個非聚簇索引 – 2009-09-08 17:15:38

+0

同意,NC索引將獲得與添加MD5或其他哈希相同或相似的性能。如果每個網址的表名記錄比例很高,我會考慮使用兩個表結構,其中唯一的網址保存在tblUrls中,而tablename只存儲相應的鍵。這可能會稍微提高插入性能,但也會降低存儲要求並具有其他一些優點,具體取決於底層應用程序。 – mjv 2009-09-08 17:21:24

0

我認爲CRC32對於這個角色實際上會更好,因爲它更短,並且可以節省更多的SQL空間。如果您收到很多查詢,那麼對象是否可以節省空間?如果它能完成這項工作,我會說去做。

儘管由於它只有32位,並且長度較短,所以它不像MD5那樣獨特。你將不得不決定你是否想要獨特的,或者如果你想節省空間。

我仍然認爲我會選擇CRC32。

我的系統每秒鐘產生大約4k個查詢,我使用CRC32作爲鏈接。

+0

您可以將完整的url始終存儲在單獨的列中,並要求MySQL比較兩者:相同的CRC32和相同的完整URL。 – 2009-09-09 02:33:19

+0

請試試這個,謝謝! :P – Homework 2009-09-09 18:24:06

-1

如果趨勢是在選擇語句的結果相當高,另一種解決方案是有一個單獨的表格來跟蹤計數。顯然,使用這種技術有很高的懲罰性,但如果這個特定的查詢是一個常見的查詢並且速度太慢,這可能是一個解決方案。

這個解決方案涉及顯而易見的權衡,您可能不希望在插入新記錄的每個單獨插入之後更新此第二個表,因爲這會降低插入速度。

0

使用內置的索引永遠是最好的,或者你應該自願加入到他們的基本代碼反正;)

當使用散列,創建散列和URL 2列索引。如果您只選擇索引中的第一對字母,它仍然會完成匹配,但它不會索引更多的前幾個字母。

事情是這樣的:

INDEX(CRC32_col, URL_col(5)) 

無論是哈希會在這種情況下工作。這是對空間與速度的權衡。

此外,該查詢會快很多:

SELECT * FROM table WHERE hash_col = 'hashvalue' AND url_col = 'urlvalue' LIMIT 1; 

這將找到的第一個值,並停止。比COUNT(*)計算找到許多匹配要快得多。

最好的選擇是爲每個變體和基準測試用例。

-1

如果你選擇一個散列,你需要考慮到collissions。即使是像MD5這樣的大散列,你也必須考慮meet-in-the-middle概率,更好的稱爲birthday attack。對於像CRC-32這樣的較小的散列,衝突概率將非常大,並且您的WHERE必須指定散列完整的URL。

但我得問,這是花費你的努力的最佳方式?還有沒有其他的優化?除非您有明確的指標和測量指示此問題是系統的瓶頸,否則您可能會做得過早優化。畢竟,這種尋求是數據庫優化的(所有這些),並且通過做一些類似哈希的事情可能會降低性能(例如,由於哈希與URL有不同的分佈,因此索引可能會變得碎片化)。

0

大多數SQL引擎不是在內部使用哈希函數來進行文本列搜索嗎?

0

如果您打算使用散列鍵並且擔心碰撞,請使用兩個不同的散列函數並連接兩個散列值。

但即使您這樣做,您也應該始終將原始關鍵值存儲在該行中。

相關問題