標籤:一個資料庫 意思 有關 rar 二次 提高 hash演算法 好處 mic
需求案例:需要把字串存入資料庫,並且要求資料庫中不能有重複的字串,由此就引出了將字串hash成特定的hash值,依靠查詢hash值是否重複來判斷字串是否重複。這樣做的好處在於查詢重複字串的代價太大,因為字串可能會非常長,進行逐個比較非常消耗資料庫的效能,如果將字串hash之後,依靠hash值來查重就顯得輕便很多了,因為hash值通常都比字串本身短很多。由於使用的是C#,自然而然就用了string的GetHashCode函數,MSDN上說該函數得到的傳回值可以唯一區別一個string,意思就是相同的字串肯定會得到相同的hash值,不同的字串的hash值肯定不一樣。當時還在疑惑,這個函數的傳回值是int型,算起來也就幾十億,但是字串的組合卻是無窮的啊,微軟是怎麼實現唯一性的呢?
測試結果:調試代碼發現用hash值查詢一個資料庫中已經存在的string,居然說沒有重複!這就相當讓人費解了,string已經存在了,那麼其hash值也肯定已經存在在資料庫中,怎麼會說沒有重複呢?仔細debug代碼,驚訝的發現原來string的hash值居然變了,變成了一個和資料庫中完全不同的值。
那麼為什麼同一個string,兩次運行GetHashCode得到的傳回值卻不一樣呢?
原來GetHashCode只是保證在同一個進程的記憶體空間中,string的傳回值可以唯一區別一個string。在同一個進程的記憶體空間中,每個string的hash值都被微軟保證不會重複(除非兩個string的內容一樣),雖然字串的組合是無限的,但是對於一個進程的記憶體空間,頂多就幾個G的,幾個G的記憶體所能容納的string的組合就變成了“有限的”了,int型的幾十億足夠來保證這些“有限的”string組合有不同的hash值。
但是微軟不保證同一個string在調用GetHashCode之後得到的傳回值是相同的!因為int就幾十億,如果用來保證每次調用得到的傳回值相同,那麼勢必出現hash值的碰撞。
這也是為什麼MD5,SHA2等hash演算法得到的傳回值都是128位或者256位的原因,因為只有足夠長,才能保證少發生碰撞或者發生碰撞之後可以二次hash。
PS:看看微軟對這個函數的備忘
http://msdn.microsoft.com/zh-cn/library/system.string.gethashcode.aspx
備忘
GetHashCode 的行為取決於它的實現,此實現可能會從一個通用語言執行平台版本更改為另一個版本。 原因可能是為了提高 GetHashCode 的效能。
說明說明
如果兩個字串對象相等,則 GetHashCode 方法返回相同的值。 但是,每個唯一的字串值並沒有唯一的雜湊碼值。 不同的字串可以返回相同的雜湊碼。
有關雜湊碼的更多資訊,請參見 Object.GetHashCode。
注意 .NET string.GetHashCode() 用法