海量数据统计通解之 超长型字符串的判重与统计——HASH与Trie树双剑合璧!!

在很多情况下我们分割文件,判重和统计数据时都需要借助HASH函数的帮助,例如MD5,SHA1等。例如我现在有50亿个长字符串,每一个字符串1k。我现在希望你统计出来各个字符串出现的频度,给出TOP X神马的。


1个1K的字符串我自认为Trie树是不适合的。因此我这个有限的脑容量中可以想到的办法就是将所有字符串计算MD5/SHA1,从而将每一个字符串缩减到16/20字节。HASH值相同的数据,我们就认为他们是一样的。


你当然希望这样一件事:那就是计算出来的HASH值总是代表它的存储下标


可是这件事你估计也就是只敢想想而已,假设我们用SHA1 HASH,那么结果就是20字节,如果直接对应数组下标,那你得申请多少的内存啊?


我可以告诉你答案,即使我们用位映射(既HASH值代表这一位被置1),那也需要是2的160次个位。换成字节是多少呢?2的157次方。1G的内存是多少呢?2的30次方个字节。


刚才谁说要把HASH值对应存储下标来的?拉出去枪毙了!



在被人拖走前,你可能会大喊,我可以分割这些HASH,把在同一个HASH范围内的数据都归纳到一个文件中,然后利用首地址和偏移量的方法来将HASH值对应到直接存储位置上去!!!


现在让我们来看看怎么分割,如果你想把2^160位分割成每个占用2^30个位的子文件,那你需要把整个文件分割成2^130份,即使排除那些空的文件,50亿个数据还是有可能导致数十万的零散文件。我个人觉得你不用挣扎了……就像上面说的,把HASH当成直接存储地址,真的只能想想。


HASH值既然不能被当作存储下标,或者位所映射的位置,那么有什么特性能有助于我们统计数据呢?刚才我说了一点,HASH 1 = HASH 2 代表 串1 = 串 2,我们再看看HASH值本身,是不是可以被理解为一个长20字节的数据串或者一个字符长度为40个的字符串呢{比如SHA1:01020304050607080900AABBCCEEFF0A0B0C0D0E,自己数是不是40个字符}。


面对四十个字符,Trie树不需要再怕什么了吧。如果还嫌40个字符长,那么我们先可以构建一个10字符的Trie,把具有前10个相同前缀的数据扔同一个文件里面。这样等价于只需要再比较后30个字符了(每一个文件分块的数据都具有同样的前10个字符了吗)。30如果不行,就再建10层,再这样划分。



总结一下:HASH值可以有效的将长字符串转成固定长度的短字符串(比如SHA1就把长字符串转成40个字符的短串)。面对短串,可以构建Trie树判重或者统计

你可能感兴趣的:(算法,存储,c)