mysql – 考虑RAM的url或hashing索引
作者:互联网
我正在开发一个项目,每天需要添加/更新大约100万个网址.有些日子主要是更新,有些日子大多是添加,有些日子是混合.
因此,在每个查询中都需要在url表中查找url的唯一性.
如何查找url的速度非常快,因为目前index设置在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和磁盘空间的低负载.你说的话?
解决方法:
在阅读完所有问题(unique constraint makes hashes useless?,512 bit hash vs 4 128bit hash和url text compression (not shortening) and storing in mysql)后,我了解到您的问题或多或少存在以下问题:
“I need to store +150M URLs in mySQL, using 8GB of RAM, and still have a good performance on writing them all and retrieving them, because daily I’ll update them, so I’ll retrive a lot of URLs, check them against the database. Actually it has 50M URLs, and will grow about 1M each day in the following 3 monts.”
是吗?
以下几点很重要:
您将保存的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 URL,因此可以根据它们生成统计信息,以生成更好的字典.
使用散列:在这种情况下,散列是大小和安全性之间的权衡.如果发生碰撞会有多糟糕?
在这种情况下,您可以使用birthday paradox来帮助您.
阅读文章以了解问题:如果所有输入(URL中可能的字符)都相同,则可能会导致碰撞的可能性.并且可以计算相反的结果:给定您可接受的碰撞概率和文件数量,您的范围应该有多宽?由于您的范围与哈希函数生成的位数完全相关…
编辑:如果你有一个散列函数给你128位,你将有2 ^ 128个可能的结果.所以,生日悖论中的“范围”是2 ^ 128:就像你的年份有2 ^ 128天而不是365.所以,你计算碰撞的概率(“两个文件在同一天出生,有一个有2 ^ 128天而不是365天的年份.如果你选择使用给你512位的哈希,你的范围将从0到2 ^ 512 ……
并且,再次考虑到RFC:并非所有字节(256个字符)在Internet / URL世界中都有效.因此,碰撞的可能性降低.对你更好 :).
标签:crc32,mysql,md5,url,ram 来源: https://codeday.me/bug/20191006/1862908.html