PHP几个几十个G大文件数据统计并且排序处理

诸多大互联网公司的面试都会有这么个问题,有个4G的文件,如何用只有1G内存的机器去计算文件中出现次数最多的数字(假设1行是1个数组,例如QQ号 码)。如果这个文件只有4B或者几十兆,那么最简单的办法就是直接读取这个文件后进行分析统计。但是这个是4G的文件,当然也可能是几十G甚至几百G的文 件,这就不是直接读取能解决了的。

同样对于如此大的文件,单纯用PHP做是肯定行不通的,我的思路是不管多大文件,首先要切割为多个应用可以承受的小文件,然后批量或者依次分析统计小文件后再把总的结果汇总后统计出符合要求的最终结果。类似于比较流行的MapReduce模型,其核心思想就是“Map(映射)”和“Reduce(化简)”,加上分布式的文件处理,当然我能理解和使用到的只有Reduce后去处理。

假设有1个10亿行的文件,每行一个6位-10位不等的QQ号码,那么我需要解决的就是计算在这10亿个QQ号码中,重复最多的前10个号码,使用下面的PHP脚本生成这个文件,很可能这个随机数中不会出现重复,但是我们假设这里面会有重复的数字出现。

$fp = fopen(‘qq.txt‘,‘w+‘);
for( $i=0; $i<1000000000; $i++ ){
    $str = mt_rand(10000,9999999999)."\n";
    fwrite($fp,$str);
}
fclose($fp);

生成文件的世界比较长,Linux下直接使用php-client运行PHP文件会比较节省时间,当然也可以使用其他方式生成文件。生成的文件大约11G。

然后使用Linux Split切割文件,切割标准为每100万行数据1个文件。

split -l 1000000 -a 3 qq.txt qqfile

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

$results = array();
foreach( glob(‘/tmp/qq/*‘) as $file ){
    $fp = fopen($file,‘r‘);
    $arr = array();
    while( $qq = fgets($fp) ){
        $qq = trim($qq);
        isset($arr[$qq]) ? $arr[$qq]++ : $arr[$qq]=1;
    }
    arsort($arr);
    //以下处理方式存在问题
    do{
        $i=0;
        foreach( $arr as $qq=>$times ){
            if( $i > 10 ){
                isset($results[$qq]) ? $results[$qq]+=$times : $results[$qq]=$times;
                $i++;
            } else {
                break;
            }
        }
    } while(false);
    fclose($fp);
}
if( $results ){
    arsort($results);
    do{
        $i=0;
        foreach( $results as $qq=>$times ){
            if( $i > 10 ){
                echo $qq . "\t" . $times . "\n";
                $i++;
            } else {
                break;
            }
        }
    } while(false);
}

这样每个样本取前10个,最后放到一起分析统计,不排除有个数在每个样本中都排名第11位但是总数绝对在前10的可能性,所以后面统计计算算法还需要改进。

也许有人说使用Linux中的awk和sort命令可以完成排序,但是我试了下如果是小文件还可以实现,但是11G的文件,不管是内存还是时间都无法承受。下面是我改的1个awk+sort的脚本,或许是写法有问题,求牛人指导。

awk -F ‘\\@‘ ‘{name[$1]++ } END {for (count in name) print name[count],count}‘ qq.txt |sort -n > 123.txt

awk -F ‘\\@‘ ‘{name[$1]++ } END {for (count in name) print name[count],count}‘ qq.txt |sort -n > 123.txt

出处:http://www.feiyan.info/50.html

时间: 2024-08-11 03:30:09

PHP几个几十个G大文件数据统计并且排序处理的相关文章

所经历的大文件数据导出(后台执行,自动生成)

所经历的大文件数据导出(后台执行,自动生成) http://www.cnblogs.com/fanfan259/p/4710019.html 阅读目录 一.前言 二.生成excel文件 三.让程序在后台执行 四.显示文件生成进度 五.下载文件 六.上线后出现的问题 七.相应的后续优化 八.后记 一.前言 记录一下以前做的后台excel格式导出统计信息的功能,也是最近同事问到了相关东西,一时之间竟忘了具体的细节,因此记录一下: 大家知道,excel导出数据的功能,后台几乎是必须功能,一般都是点击后

大文件/数据网络传输方法总结(转载)

网络编程中不免会遇到需要传输大数据.大文件的情况,而由于socket本身缓冲区的限制,大概一次只能发送4K左右的数据,所以在传输大数据时客户端就需要进行分包,在目的地重新组包.而实际上已有一些消息/通讯中间件对此进行了封装,提供了直接发送大数据/文件的接口:除此之外,利用共享目录,ftp,ssh等系统命令来实现大文件/数据也不失为一种好的方法. 1.基础的基于socket进行传输 基础的基于socket进行传输关键在于控制,需要自己行分包和组包. ////////////////////////

Java NIO内存映射---上G大文件处理

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果. 一.java中的内存映射IO和内存映射文件是什么? 内存映射文件非常特别,它允许Java程序直接从内存中读取文件内容,通过将整个或部分文件映射到内存,由操作系统来处理加载请求和写入文件,应用只需要和内存打交道,这使得IO操作非常快.加载内存映射文件所使用的内存在Java堆区之外.Java编程语言

Java NIO内存映射---上G大文件处理(转)

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果. 一.java中的内存映射IO和内存映射文件是什么? 内存映射文件非常特别,它允许Java程序直接从内存中读取文件内容,通过将整个或部分文件映射到内存,由操作系统来处理加载请求和写入文件,应用只需要和内存打交道,这使得IO操作非常快.加载内存映射文件所使用的内存在Java堆区之外.Java编程语言

用php导入10W条+ 级别的csv大文件数据到mysql。导出10W+级别数据到csv文件

转自:http://blog.csdn.net/think2me/article/details/12999907 1. 说说csv 和 Excel 这两者都是我们平时导出或者导入数据一般用到的载体.两者有什么区别呢?csv 格式更兼容一点.那么共同点都是GBK格式的,非UTF8.所以我们上传文件的时候,老是出现乱码,就是编码问题没有转好导致. 2. 推荐的几种方法 1. 函数 fgetss($handel);  返回字符串.它就是strip_tags(fget($handel))的组合读取cs

Sybase IQ如何将大文件数据迅速加载到数据库

试想一下,如果一个文件5G.10G甚至更大.如何将它迅速地加载到数据库指定的表呢?我们看看Sybase IQ是如何迅速地将表的数据加载到数据库的. 数据文件格式: 1440,2011-01-09 00:00:00,1,珠海,1,C网,8612345678222,221943,1,12175,1,12,14426467,1191632,9,1440,2011-01-09 00:00:00,1,珠海,1,C网,8612345678222,968852,1,82077,1,7,2430696,1349

如何实现大文件数据上传

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms; namespace WinShowDown{ public partial class FrmMain : Form { public FrmMa

rsync增量传输大文件优化技巧

问题 rsync用来同步数据非常的好用,特别是增量同步.但是有一种情况如果不增加特定的参数就不是很好用了.比如你要同步多个几十个G的文件,然后网络突然断开了一下,这时候你重新启动增量同步.但是发现等了好久都没有进行数据传输,倒是机器的IO一直居高不下. 原因 rsync具体的增量同步算法不太清楚.根据它的表现来看,可能在增量同步已经存在的一个文件时,会校验已传输部分数据是否已源文件一致,校验完成才继续增量同步这个文件剩下的数据.所以如果对一个大文件以这样的算法来增量同步是非常花时间并且占用IO资

内存映射文件处理大文件

先说结论:使用内存映射文件来处理大文件可以提高效率. 为什么呢? 我们先来看看如果不使用内存映射文件的处理流程是怎样的,首先我们得先读出磁盘文件的内容到内存中,然后修改,最后回写到磁盘上.第一步读磁盘文件是要经过一次系统调用的,它首先将文件内容从磁盘拷贝到内核空间的一个缓冲区,然后再将这些数据拷贝到用户空间,实际上是两次数据拷贝.第三步回写也一样也要经过两次数据拷贝. 所以我们基本上会有四次数据的拷贝了,因为大文件数据量很大,几十GB甚至更大,所以拷贝的开销是非常大的. 而内存映射文件是操作系统