2011-10-31 24 views
2

我最近以GetHashCode()的方式指示了我,特別是「GetHashCode的使用者不能依賴它在一段時間內或跨應用程序域保持穩定」(From一個Eric Lippert blog article)。創建用於數據庫的哈希碼(即,不使用GetHashCode)

不幸的是,我一直在數據庫中使用它來嘗試加快查找速度(通過插入GetHashCode的結果而不是對文本字符串進行搜索)。我現在意識到這是一件非常糟糕的事情。

所以我仍然想知道我能做些什麼。 有什麼給定的字符串將被保證返回一個明顯的抗碰撞整數,我可以用於查找?

我可以自己寫一些東西,但我希望能夠有內置的東西,我可以使用,而不必去加密庫中的東西,感覺有點重量級。

+3

爲什麼你想這首先呢?讓數據庫做它的意義。 – SLaks

+0

@SLaks:這可能是我選擇了一些關於數據庫的老婆婆的故事,但我認爲如果你想查找一個50個字符的字符串,它會比根據該字符串查找int更慢。考慮一下,你可能是正確的,如果我將列索引,它會做我想要的,然後一些。自從獲得校驗和或類似的結果以來,如果有答案,我仍然感興趣,因爲我認爲這是一個非常有用的事情。 – Chris

+0

@Chris,「獲取校驗和或類似」通常不是很有用,對於某些特定情況非常有用。在每種情況下,你對校驗和/哈希碼都有不同的要求,所以你應該使用不同的算法。 – svick

回答

3

我鼓勵你考慮其他人的看法:讓數據庫做它擅長的事情。爲了優化查找而創建哈希代碼表明表中的索引不是它們應該是的。

也就是說,如果你真的需要的哈希代碼:如果你想有一個32位或64位的散列碼

你不說。這將爲一個字符串創建一個64位的哈希碼。這是合理的碰撞抵抗。

public static long ComputeHashCode(string url) 
{ 
    const ulong p = 1099511628211; 

    ulong hash = 14695981039346656037; 

    for (int i = 0; i < url.Length; ++i) 
    { 
     hash = (hash^url[i]) * p; 
    } 

    // Wang64 bit mixer 
    hash = (~hash) + (hash << 21); 
    hash = hash^(hash >> 24); 
    hash = (hash + (hash << 3)) + (hash << 8); 
    hash = hash^(hash >> 14); 
    hash = (hash + (hash << 2)) + (hash << 4); 
    hash = hash^(hash >> 28); 
    hash = hash + (hash << 31); 

    if (hash == (ulong)UNKNOWN_RECORD_HASH) 
    { 
     ++hash; 
    } 
    return (long)hash; 
} 

注意,這是一個哈希代碼和碰撞的可能性如果你有多達數十億的記錄是非常小的。經驗法則:當項目數量超出散列碼範圍的平方根時,您有50%的碰撞機會。這個哈希碼的範圍是2^64,所以如果你有2^32個項目,你的碰撞機率約爲50%。

請參閱http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=792http://en.wikipedia.org/wiki/Birthday_paradox#Probability_table瞭解更多信息。

+0

這是什麼UNKNOWN_RECORD_HASH常量(我認爲它是一個常量)? – Chris

+0

我把這個標記爲正確的答案,因爲你告訴我不要這麼傻,並且回答了我的問題。 :) – Chris

+0

'UNKNOWN_RECORD_HASH'是我用來指示記錄沒有哈希碼的值。我認爲它與我的系統中的'0'相等,但您可以將其設置爲任意常量值。該檢查用於防止該方法生成未知記錄哈希值。 –

1

正如SLaks在評論中指出的那樣,查找數據是數據庫擅長的。

如果您需要快速查找,請在該列上創建一個索引。至少,你不必再處理碰撞。

+0

我認爲你是對的。現在我只需要去修復我所有可怕的代碼。 ;-) – Chris