我正在开发一个项目,每天需要添加/更新大约100万个网址。有些日子主要是更新,有些日子大多是添加,有些日子是混合。
因此,在每个查询中都需要在url表中查找url的唯一性。
如何查找url的速度非常快,因为目前索引设置在url列并且运行良好但是在未来几周内,如果索引保留在同一列上并且将添加新记录,则RAM将不够用百万。
这就是为什么我正在寻找一个解决方案,以便当总共有1.5亿个网址时,它的查找应该很快。我正在考虑在md5上创建索引,但后来担心碰撞机会。一位朋友告诉我也计算crc32 hash并与md5连接以使碰撞可能性为零并将其存储在二进制(20)中,这样只将20个字节作为索引而不是255当前varchar(255)设置为url列数据类型。
目前总共有大约5000万网址和8GB内存工作正常。
昨天,我问了一个与同一个项目有关的问题url text compression (not shortening) and storing in mysql。
[编辑] 我想到了另一种解决方案,只能以十进制形式放入crc32哈希以加快查找速度。并在应用程序级别移植检查返回的记录数。如果返回的记录超过1条,则还应匹配精确的URL。 这样,通过为每行存储4个字节而不是20个字节(md5 + crc32),同时保持RAM和磁盘空间的低负载,也可以避免冲突。你说什么?
答案 0 :(得分:6)
在阅读完所有问题(unique constraint makes hashes useless?,512 bit hash vs 4 128bit hash和url text compression (not shortening) and storing in mysql)后,我了解到您的问题或多或少存在以下问题:
是吗?“我需要在mySQL中存储+ 150M的URL,使用8GB的RAM,并且在编写所有内容并检索它们时仍然具有良好的性能,因为每天我都会更新它们,所以我会检索很多URL根据数据库检查它们。实际上它有50M的URL,并且在以下3个monts中每天将增长大约1M。“
以下几点很重要: 您将保存的URL格式如何?您是需要回读URL还是仅更新有关它的信息,但从不基于部分URL进行搜索等?
假设URL =“http://www.somesite.com.tv/images/picture01.jpg”并且您要存储所有内容,包含文件名。 如果不同,请提供更多详细信息或更正我的答案假设。
如果可以通过替换URL中的某些字符组来节省空间。并非所有ASCII字符在URL as you can see here: RFC1738中都有效,因此您可以使用它们来表示(和压缩)URL。例如:使用字符0x81表示“http://”可以使您保存6个字符,0x82代表“.jpg”可以保存另外3个字节等。
有些词可能很常见(如“图片”,“图片”,“视频”,“用户”)。如果您选择使用字符0x90至0x9f +任何其他字符(因此,0x90 0x01,0x90 0x02,0x90 0xfa)来编码此类字,您可以使用16 * 256 = 4,096“字典条目”来编码最常用的字。您将使用2个字节来表示4-8个字符。
编辑,因为您可以在上面提到的RFC中阅读,在URL中您只能使用可打印的ASCII字符。这意味着只应使用字符0x20到0x7F,并在RFC中进行一些观察。因此,不应使用0x80之后的任何字符(十六进制表示法,即ASCII表中的十进制字符128)。所以,如果可以选择一个字符(比如说0x90)作为一个标志来表示“后面的字节是字典中的一个指示,我将使用的索引”。一个字符(0x90)* 256个字符(0x00到0xFF)=字典中的256个条目。但你也可以选择使用字符0x90到0x9f(或十进制的144到159)来表示它们是字典的标志,从而为你提供16 * 256种可能性......
这两种方法可以为您节省数据库中的大量空间并且是可逆的,无需担心冲突等。您可以在应用程序中简单地创建字典并使用它来编码/解码URL,非常快速,使您的数据库更轻松。
由于您已有+ 50M网址,因此您可以根据这些网址生成统计信息,以生成更好的字典。
使用哈希:在这种情况下,哈希是大小和安全性之间的权衡。如果发生碰撞会有多糟糕? 在这种情况下,您可以使用birthday paradox来帮助您。
阅读文章以了解问题:如果所有输入(URL中可能的字符)都相同,则可能会导致碰撞的可能性。并且可以计算相反的结果:给定您可接受的碰撞概率和文件数量,您的范围应该有多宽?因为你的范围与哈希函数生成的位数完全相关......
编辑:如果您有一个散列函数可以提供128位,那么您将获得2 ^ 128个可能的结果。所以,生日悖论中的“范围”是2 ^ 128:就像你的年份有2 ^ 128天,而不是365.所以,你计算碰撞的概率(“两个文件 < em>出生在同一天,年有2 ^ 128 天而不是365天。如果你选择使用散列给出你是512位,你的范围将从0到2 ^ 512 ......
而且,再次考虑到RFC:并非所有字节(256个字符)在Internet / URL世界中都有效。因此,碰撞的可能性降低。对你更好:)。