C# 如何快速散列URL

C# 如何快速散列URL,c#,algorithm,c#-4.0,hash,C#,Algorithm,C# 4.0,Hash,我有一个独特的情况,需要动态生成哈希。这是我的情况。这个问题涉及到。我需要在数据库中存储许多需要索引的URL。URL的长度可以超过2000个字符。数据库抱怨超过900字节的字符串无法索引。我的解决方案是使用MD5或SHA256散列URL。我不确定使用哪种哈希算法。这是我的要求 最小冲突的最短字符长度 需要非常快速。我将在每个页面请求上散列refereURL 冲突需要最小化,因为数据库中可能有数百万个URL 我不担心安全问题。我担心字符长度、速度和碰撞。有谁知道这方面的好算法吗?我建议使用Sy

我有一个独特的情况,需要动态生成哈希。这是我的情况。这个问题涉及到。我需要在数据库中存储许多需要索引的URL。URL的长度可以超过2000个字符。数据库抱怨超过900字节的字符串无法索引。我的解决方案是使用MD5或SHA256散列URL。我不确定使用哪种哈希算法。这是我的要求


  • 最小冲突的最短字符长度
  • 需要非常快速。我将在每个页面请求上散列refereURL
  • 冲突需要最小化,因为数据库中可能有数百万个URL

我不担心安全问题。我担心字符长度、速度和碰撞。有谁知道这方面的好算法吗?

我建议使用
System.Security.Cryptography.SHA1Cng
类。它有160位或20字节长,所以应该足够小。如果你需要它是一个字符串,它将只需要40个字符,所以应该适合你的需要。它也应该足够快,据我所知,还没有发现碰撞。

我个人会使用。这是基本的散列函数。老实说,与其他实现相比,我不知道它的性能如何,但它应该很好

您命名的两个哈希函数中的任何一个都应该足够快,这样您就不会注意到它们之间有太大的差异。除非这个网站需要超高性能,否则我不会太担心它们。我个人可能会选择MD5。可以将其格式化为64个字符的十六进制字符串或44个字符的基64字符串

我之所以选择MD5,是因为您不太可能遇到冲突,即使遇到冲突,您也可以使用“where urlhash=@hash and url=@url”来构造查询。数据库引擎应该计算出一个索引了,另一个没有,并使用这些信息进行合理的搜索

如果存在冲突,urlhash上的索引扫描将返回少量结果,这些结果很容易进行文本比较,以获得正确的结果。不过,这不太可能经常相关。这样碰撞的几率很低。

一个简单的例子:

URLString.GetHashCode().ToString("x")

虽然MD5和SHA1都被证明在碰撞预防至关重要的地方无效,但我怀疑对于您的应用来说,两者都足够了。我不确定,但我怀疑MD5将是两种算法中更简单、更快的一种

在您的情况下,我不会使用任何加密散列函数(即MD5,SHA),因为它们的设计考虑到了安全性:它们主要是为了尽可能难以找到具有相同散列的两个不同字符串。我想这对你来说不是问题。(当然,随机冲突的可能性是散列固有的)

我强烈建议不要使用
String.GetHashCode()
,因为实现未知,而且MSDN说它可能在不同版本的框架之间有所不同。甚至x86和x64版本之间的结果也可能不同。因此,在尝试使用较新(或不同)版本的.NET framework访问同一数据库时,您会遇到麻烦

我在Wikipedia()上找到了
hashCode
的Java实现算法,它似乎很容易实现。即使是简单的实现也比MD5或SHA imo的实现要快。您还可以使用
long
值来降低冲突的概率


还有一个对.NET
GetHashCode
实现的简短分析(不是算法本身,而是一些实现细节),我想您也可以使用这个。(或者尝试以类似的方式实现Java版本…

反映了.net 4.0中GetHashCode函数的源代码

public override unsafe int GetHashCode()
{
    fixed (char* str = ((char*) this))
    {
        char* chPtr = str;
        int num = 0x15051505;
        int num2 = num;
        int* numPtr = (int*) chPtr;
        for (int i = this.Length; i > 0; i -= 4)
        {
            num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
            if (i <= 2)
            {
                break;
            }
            num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
            numPtr += 2;
        }
        return (num + (num2 * 0x5d588b65));
    }
}
public覆盖不安全的int-GetHashCode()
{
固定(char*str=((char*)this))
{
char*chPtr=str;
int num=0x15051505;
int num2=num;
int*numPtr=(int*)chPtr;
对于(int i=this.Length;i>0;i-=4)
{
num=((num>0x1b))^numPtr[0];
如果(i 0x1b))^numPtr[1];
numpr+=2;
}
返回值(num+(num2*0x5d588b65));
}
}

有O(n)个简单操作(+,您可能需要查看以下项目:

并查看以下热门话题列表以获得完美的哈希:

您还可以考虑在SQL中使用全文索引而不是散列:


那么你对url做了什么?Git使用的是SHA1,它散列的数据比简单的url多得多。我使用SHA1,你并不真正需要SHA2。url将存储在数据库中,没有索引。我将使用has值搜索给定的url。但url将用于生成给定网页上的链接。“最小冲突的最短字符长度”-这并不是一个真正有意义的要求。假设一个“完美的“哈希函数,冲突概率将与哈希长度成反比。您需要将哈希长度和数据库中的URL总数插入生日悖论公式,以获得冲突概率,并判断其是否“足够低”。你说你需要快速,但听起来像是在抓取网页。任何网络往返都将比散列短字符串慢几个数量级。在base64编码中,160位肯定是28个字符?即使使用十六进制,它仍然只有40个字符(每个字符4位)。@Chris Try&see
Convert.ToBase64String(新字节)[20] ).Length
@Chris:我的数学有点不对劲:)而且我实际上在考虑十六进制,因为我对这个网站不太了解。它们可能需要是URL frie