设为首页 收藏本站
查看: 456|回复: 0

[经验分享] PHP/Shell大文件数据统计并且排序

[复制链接]

尚未签到

发表于 2017-4-9 07:14:52 | 显示全部楼层 |阅读模式
诸多大互联网公司的面试都会有这么个问题,有个4G的文件,如何用只有1G内存的机器去计算文件中出现次数做多的数字(假设1行是1个数组,例如QQ号码)。如果这个文件只有4B或者几十兆,那么最简单的办法就是直接读取这个文件后进行分析统计。但是这个是4G的文件,当然也可能是几十G甚至几百G的文件,这就不是直接读取能解决了的。
同样对于如此大的文件,单纯用PHP做是肯定行不通的,我的思路是不管多大文件,首先要切割为多个应用可以承受的小文件,然后批量或者依次分析统计小文件后再把总的结果汇总后统计出符合要求的最终结果。类似于比较流行的MapReduce模型,其核心思想就是“Map(映射)”和“Reduce(化简)”,加上分布式的文件处理,当然我能理解和使用到的只有Reduce后去处理。
假设有1个10亿行的文件,每行一个6位-10位不等的QQ号码,那么我需要解决的就是计算在这10亿个QQ号码中,重复最多的前10个号码,使用下面的PHP脚本生成这个文件,很可能这个随机数中不会出现重复,但是我们假设这里面会有重复的数字出现。
1$fp = fopen('qq.txt','w+');

2for( $i=0; $i<1000000000; $i++ ){

3    $str = mt_rand(10000,9999999999)."\n";

4    fwrite($fp,$str);

5}

6fclose($fp);



生成文件的世界比较长,Linux下直接使用php-client运行PHP文件会比较节省时间,当然也可以使用其他方式生成文件。生成的文件大约11G。
然后使用Linux Split切割文件,切割标准为每100万行数据1个文件。
1split -l 1000000 -a 3 qq.txt qqfile



qq.txt被分割为名字是qqfileaaa到qqfilebml的1000个文件,每个文件11mb大小,这时再使用任何处理方法都会比较简单了。我还是使用PHP进行分析统计:
01$results = array();

02foreach( glob('/tmp/qq/*') as $file ){

03    $fp = fopen($file,'r');

04    $arr = array();

05    while( $qq = fgets($fp) ){

06        $qq = trim($qq);

07        isset($arr[$qq]) ? $arr[$qq]++ : $arr[$qq]=1;

08    }

09    arsort($arr);

10    //以下处理方式存在问题

11    do{

12        $i=0;

13        foreach( $arr as $qq=>$times ){

14            if( $i > 10 ){

15                isset($results[$qq]) ? $results[$qq]+=$times :$results[$qq]=$times;

16                $i++;

17            } else {

18                break;

19            }

20        }

21    } while(false);

22    fclose($fp);

23}

24if( $results ){

25    arsort($results);

26    do{

27        $i=0;

28        foreach( $results as $qq=>$times ){

29            if( $i > 10 ){

30                echo $qq . "\t" . $times . "\n";

31                $i++;

32            } else {

33                break;

34            }

35        }

36    } while(false);

37}



这样每个样本取前10个,最后放到一起分析统计,不排除有个数在每个样本中都排名第11位但是总数绝对在前10的可能性,所以后面统计计算算法还需要改进。
也许有人说使用Linux中的awk和sort命令可以完成排序,但是我试了下如果是小文件还可以实现,但是11G的文件,不管是内存还是时间都无法承受。下面是我改的1个awk+sort的脚本,或许是写法有问题,求牛人指导。
1awk -F '\\@' '{name[$1]++ } END {for (count in name) print name[count],count}' qq.txt |sort -n > 123.txt



互联网几何级增长,未来不管是大文件处理还是可能存在的大数据都存在很大的需求空间。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-362183-1-1.html 上篇帖子: PHP中yii的一些最常用知识 下篇帖子: PHP网站安装程序制作 (附:模块检测的方法)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表