有几个问题需要确认一下: 1、你说的 已经序列化后 是指用 serialize 函数的结果吗? 2、你说的 用户ID是key,时间是value 中的时间是计算好的在线时间,还是什么? 从 将相同key的value相加 来看,应该是计算好的在线时间由于数据量比较大,最好用数据库做载体: 新建一表 create table test (id varchar(20), num int) 用临时表就可以了 create temporary table test (id varchar(20), num int)//在循环中 $files = scandir("目录名"); foreach($files as $filename){ //读取文件并反序列化到数组 if(is_file($filename)){ $ar = unserialize(file_get_contents($filename)); //遍历数组将数据插入表 foreach($ar as $k=>$v) { mysql_query("insert into test (id, num) values ('$k', $v)"; } } }当全部文件都加载后,执行查询 select id, sum(num) as num from test group by id order by num desc limit 1000 如果内存足够大,也可以用纯php代码实现 $out = array(); //结果数组 //在循环中 $files = scandir("目录名"); foreach($files as $filename){ //读取文件并反序列化到数组 if(is_file($filename)){ $ar = unserialize(file_get_contents($filename)); //遍历数组将数据加入结果数组 foreach($ar as $k=>$v) { $out[$k] += $v; } } }//当全部文件都加载后 arsort($out); $out = array_slice($out, 0, 1000);
是的,已经用原始的数据已经计算好了每天的每个用户的在线时间用serialize序列化用存放。我只处理闭合的数据,不闭合的情况忽略不计。我现在是这么想的:将每个文件循环读取进来进行遍历,声明一个数组 h 用于存放4个月每个用户总的在线时间,取一个 k 判断这个在 h 中是否存在,如果存在将 v 相加,如果不存在 k 加入 h 。判断完之后都将 K 从原数组中删除。当然时间依旧会花很多,但是空间应该能节约吧。我就爬跑起来的时候内存被吃光,高手看下是否可行。另外排序到是没什么问题,我写了一个堆排序,不过很奇怪我用200W的数据做了一个测试,发现跟PHP内置的快速排序asort效率一样不知道是我写的那个堆排序不够优化还是asort用了什么更优秀的算法
// 读取所有文件
$files = scandir("目录名");
foreach($files as $v){
if(is_file($v)){
// 读取文件,做进一步处理
}
}至于如何加用户时间,这个帖子已经说了吧?
http://topic.csdn.net/u/20100825/09/84511f0e-e029-4e93-b956-cfc4aeb87c1d.html
逐行读取,遇到online,则将$online['username'] 赋值当前时间,遇到该用户的下一offline,则计算差值,插入数据库文件读取完毕,可以读下一文件,或者将$online非空的部分,写一个新的文件如果逐一读取文件结束,再给数据库用户字段加索引,统计一下
----------------------------------------------------------------------
不过我没这么做过,每个文件大约150万条数据吧,不清楚效率,我觉得你可以试着操作一个文件看看不能忍受,再考虑其他语言吧,不过,原理还是差不多的
1、你说的 已经序列化后 是指用 serialize 函数的结果吗?
2、你说的 用户ID是key,时间是value 中的时间是计算好的在线时间,还是什么?
从 将相同key的value相加 来看,应该是计算好的在线时间由于数据量比较大,最好用数据库做载体:
新建一表
create table test (id varchar(20), num int)
用临时表就可以了
create temporary table test (id varchar(20), num int)//在循环中
$files = scandir("目录名");
foreach($files as $filename){
//读取文件并反序列化到数组
if(is_file($filename)){
$ar = unserialize(file_get_contents($filename));
//遍历数组将数据插入表
foreach($ar as $k=>$v) {
mysql_query("insert into test (id, num) values ('$k', $v)";
}
}
}当全部文件都加载后,执行查询
select id, sum(num) as num from test group by id order by num desc limit 1000
如果内存足够大,也可以用纯php代码实现
$out = array(); //结果数组
//在循环中
$files = scandir("目录名");
foreach($files as $filename){
//读取文件并反序列化到数组
if(is_file($filename)){
$ar = unserialize(file_get_contents($filename));
//遍历数组将数据加入结果数组
foreach($ar as $k=>$v) {
$out[$k] += $v;
}
}
}//当全部文件都加载后
arsort($out);
$out = array_slice($out, 0, 1000);
■□■□■□■□■□■□■□■
□ □
■ 忍以明志 勤以致远 ■
□ □
■□■□■□■□■□■□■□■
基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
首先定义一个用户的区分方法,把所有用户分到100到200个区间,分别对应不同的文件
然后从数据文件读取用户信息,计算在线时间,累加到索引文件中
最后从每个文件中取最前面的一些用户进行比较
整体难度不大,就是处理起来比较麻烦不想自己动手写索引的话可以用lucence来实现索引
2、使用Memcached缓存处理数据,把文件的内容压入缓存 进行计算
其中涉及到一些算法及排序
3、每个文件新建一个数据表 联合查询 再排序