在DB中存储C#GetHashCode()是不可靠的

时间:2011-03-18 16:31:15

标签: c# sql-server regex hash gethashcode

  

可能重复:
  How do I create a HashCode in .net (c#) for a string that is safe to store in a database?

我打算在我的数据库中存储数十万个网址。我的UrlInfo表中的每一行都是不可变的,URL本身就是逻辑主键。由于URL可能相当冗长,因此我决定将URL作为一种快速方法来查找添加新行时可能的匹配项。哈希不是我的真正关键,只是一种快速查找可能匹配的方法。此外,我每个域使用一个RegEx模式,将URL的本质提炼成可与其他URL进行比较的内容。我将RegEx的结果也存储为哈希,我不担心它是否会产生重复。

直到我了解到C#的string.GetHashCode()方法,我一直用来散列东西,并不能保证在.Net的实现中是唯一的,所以一切都很顺利。当我尝试将我的哈希函数从ASP.Net移动到SQLServer CLR代码时,我注意到了这一点。我知道,Web应用程序使用.Net 4.0和SQLServer 2008 R2,使用.Net 3.5。他们为同一个字符串产生了单独的哈希结果,所以现在我需要摆脱使用string.GetHashCode(),因为当我将应用程序升级到.Net的未来版本时,我不想担心这种变化。 / p>

所以,问题:

  1. 我的架构是否有味道,因为我在我的数据库中存储了哈希?有更好的方法吗?显然微软不希望我存储哈希结果!

  2. 有人可以为散列字符串推荐一个好的C#替换算法吗?我看到Jon's here但不确定如何修改以使用字符串(使用ascii代码循环遍历每个字符?)。

  3. 是否有比使用哈希算法更好的字符串压缩算法?

  4. 由于

    许多人的真实反应。非常感谢!!!

5 个答案:

答案 0 :(得分:3)

您总是可以使用MD5哈希,这相对较快:

public string GetUrlHash(string url) {

    byte[] hash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(url));

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < hash.Length; i++) {
        sb.Append(hash[i].ToString("X2"));
    }

    return sb.ToString();
}

这样称呼:

Console.WriteLine(this.GetUrlHash("http://stackoverflow.com/questions/5355003/storing-c-gethashcode-in-db-is-unreliable"));

得到:

> 777BED7F83C66DAC111977067B4B4385

从独特性的角度来看,这应该是相当可靠的。 MD5现在对于密码应用程序来说是不安全的,但你在这里没有这个问题。

唯一的问题是使用像这样的字符串作为表上的主键可能会出现性能问题。

您可以做的另一件事是使用URL缩短方法:使用数据库的序列生成功能,并将值(确保使用相当于LONG或BIGINT!)转换为像Base36这样的东西,它给你一个很好的,简洁的字符串。

答案 1 :(得分:1)

这里也提出了类似的问题:

How do I create a HashCode in .net (c#) for a string that is safe to store in a database?

它可以证明可以解决您的问题。

答案 2 :(得分:1)

作为一个注释,2008年的SQL Server支持(拥有)函数HASHBYTES,给定一些数据(例如一个字符串)可以生成MD2,MD4,MD5,SHA或SHA1哈希值。

答案 3 :(得分:0)

我说你可能不需要存储哈希值。

只需确保正确索引表中的URL列(唯一索引),搜索速度应该很快。

答案 4 :(得分:0)

您是否考虑过压缩字符串并存储VARBINARY?它可能要小得多,你可以直接在它上建立一个索引。