您好,欢迎访问一九零五行业门户网

php排序1亿个QQ号码

吃饱喝足了,还发贴了。
拆开分成几千份进行排序再合并。
首先先创建一个1亿个qq号的txt。
$v){ $arr = range($v*10000+10000,10000*($v+1)+9999); shuffle($arr); fputs($fp,implode(\n, $arr).\n); unset($arr);}echo microtime(true)-$st;?>
稍等一两分钟1亿个随机qq创建完成了。
qq号码范围为>10000。文件大小大概有840mb。
下面就进行分类划分成几千份文件。
以qq号码长度为文件夹,qq号码前3位为文件名。
$v) { if($v!='') { $tag = $v[0]$v[1]$v[2]; $text_arr[strlen($v)][$tag][] = $v; } } foreach ($text_arr as $k=>$v) { $n_dir = 'qq_no/'.$k; if (!is_dir($n_dir)) mkdir($n_dir); foreach ($v as $tag=>$val) { $n_tf = fopen($n_dir.'/'.$tag.'.txt', 'a+'); fputs($n_tf,implode(\n,$val).\n); } } unset($text_arr); ++$i;}echo microtime(true)-$st;?>
最后就要每个文件进行排序合并数据了。
$val){ if ($val != '.' && $val != '..') $dirs[$val] = scandir($root.'/'.$val);}foreach ($dirs as $key=>$val){ foreach ($val as $v) { if ($v != '.' && $v != '..') { $file = $root. '/' . $key . '/'. $v; $c = file_get_contents($file); $arr = explode(\n, $c); sort($arr); fputs($qq_done, implode(\n,$arr)); unlink($file); } } rmdir($root. '/' . $key);}rmdir($root);echo microtime(true)-$st;?>
总共大概花费了20多分钟。
虽然完成了,但方法很土鳖 0_0 ,坛里各位高手们改进改进啊。
回复讨论(解决方案) 没学过php 能不能用哈希散列分散去排列?
我去打酱油了。
这么晚还有人,
楼上两位吃吃瓜子吧。
强大的数组工程
交给数据裤吧
用你代码生成qq.txt,
然后直接sort,
在我的fedora(vmware)里18分钟出结果
(可能还要短一点,因为我把它放后台了)
没学过php 能不能用哈希散列分散去排列?
我也没学过,我只会c和java...哈希散列完全可以,qq号码不重复的话可以完全映射
来个c版本的
#include #define bitsperword 32#define shift 5#define mask 0x1f#define n 100000000int a[1 + n/bitsperword];void set(int i){ a[i>>shift] |= (1shift] &= ~(1shift] & (1<<(i & mask));}int main(){ int i; //初始化 for(i = 0; i < n; i++) clr(i); //读取文件,置位 while(scanf(%d, &i) != eof) set(i); for(i = 0; i < n; i++) if(test(i)) printf(%d\n, i); return 0;}
请做好边界测试
1亿个qq号码并不是1亿个1亿以内的数
10月份我一个朋友申请的qq号已是 1450250164 了
千万别小瞧了那多出来的一位
先把数据存入数据库,然后在读,这样时间会不会快,这会不会死机?
这位同学请教一下,直接sort怎么弄啊?
用你代码生成qq.txt,
然后直接sort,
在我的fedora(vmware)里18分钟出结果
(可能还要短一点,因为我把它放后台了)
这确实啊。。没考虑到这一点。
差一位就差很多了。
从容量统计上看就看出来差很多了。
大概。
6位qq号的总7mb
7位qq号的总70mb
8位qq号的总700mb
...
请做好边界测试
1亿个qq号码并不是1亿个1亿以内的数
10月份我一个朋友申请的qq号已是 1450250164 了
千万别小瞧了那多出来的一位
c的方法还得学习学习。
用数据库来排序还在测试中...
还没成功。导入是个问题。
这位同学请教一下,直接sort怎么弄啊?
引用 6 楼 helloyou0 的回复:
用你代码生成qq.txt,
然后直接sort,
在我的fedora(vmware)里18分钟出结果
(可能还要短一点,因为我把它放后台了)
就是unix的命令sort啊
改天我再试试大点的文件和mysql数据库
mysql我测好了。
引用 12 楼 ci1699 的回复:
这位同学请教一下,直接sort怎么弄啊?
引用 6 楼 helloyou0 的回复:
用你代码生成qq.txt,
然后直接sort,
在我的fedora(vmware)里18分钟出结果
(可能还要短一点,因为我把它放后台了)
就是unix的命令sort啊
改天我再试试大点的文件和mysql数据库
用mysql来排序完成了。
入库排序导出最快也要10来分钟。
相对上面php来排快了些。
说话什么都要动动手。
不抓抓还真不知哪里疼哪里痒啊。
用mysql来排序首先要入库。
第一个要解决的问题,就是把1亿个qq号入库。
总不能insert一亿次吧?
刚开始想直接把生成的qq号码转成sql直接导入。
但生成sql后1g多啊。这么大,怎么耍?
想想还是分开了几个几百mb吧。
然后就分成了几百mb一个sql导入。
这一导upu、内存就开始狂飙了,滴答了大半天没反应。
关进程查表看情况怎样,但表还是空空如也。
又没报错又没信息看。莫非文件还太大?
继续分成几十mb试试。
又是等十多分钟,但是还是失败了。报max_allowed_packet错。
改max_allowed_packet继续导,依然报错。
最后没方法试了少量数据终于找到原因拉。
是sql太长...(),(),()...的原因,那除了分下文件又得分sql了。
拆成1mb一条sql。
下面贴代码,各位朋友可以试试。
4200秒。(插到后面相对来说越来越慢) 太慢了。导出就不测了。
总结上面最佳方案就是使用myisam引擎并且无索引。
最后有几点疑问,into outfile是怎么会事的呢?
一个索引一个无索引导出写文件速度差别这么多。
还有让人郁闷的是,怎么innodb这么慢,且慢这么多?
不可想象。不玩了,睡觉了。 0_0zzzz
太牛了
真强大啊,,无语了。
强大的数组工程
既然有现成的数据文件,就没有必要去构造插入串了
set_time_limit(0);$sql =<<< sqlcreate table if not exists qq1 ( `qq` int(10) not null, key `qq` (`qq`)) engine=myisam default charset=utf8;sql;mysql_connect('localhost', 'root', '');mysql_select_db('test');mysql_query($sql);$filename = str_replace('\\', '/', realpath('qq.txt'));$sql =<<< sqlload data infile '$filename' into table qq1sql;check_speed(1);mysql_query($sql) or print(mysql_error());;check_speed();
时间: 182,955,851 微秒
内存: 664
set_time_limit(0);mysql_connect('localhost', 'root', '');mysql_select_db('test');echo '升序
';$filename = str_replace('\\', '/', dirname(__file__) . '/qq_1.txt');if(file_exists($filename)) unlink($filename);$sql =<<< sqlselect qq from qq1 order by qq asc into outfile '$filename'sql;check_speed(1);mysql_query($sql) or print(mysql_error());check_speed();echo '降序
';$filename = str_replace('\\', '/', dirname(__file__) . '/qq_2.txt');if(file_exists($filename)) unlink($filename);$sql =<<< sqlselect qq from qq1 order by qq desc into outfile '$filename'sql;check_speed(1);mysql_query($sql) or print(mysql_error());check_speed();echo '主键可不排序
';$filename = str_replace('\\', '/', dirname(__file__) . '/qq_0.txt');if(file_exists($filename)) unlink($filename);$sql =<<< sqlselect qq from qq1 into outfile '$filename'sql;check_speed(1);mysql_query($sql) or print(mysql_error());;check_speed();
升序
时间: 46,308,538 微秒
内存: 520
降序
时间: 105,860,001 微秒
内存: 432
主键可不排序
时间: 38,615,022 微秒
内存: 432
还有让人郁闷的是,怎么innodb这么慢,且慢这么多?
所有 innodb 类型表的数据被存放在一个文件 ibdata1 中,依靠文件指针来定位数据
但由于他不要求有连续的磁盘空间(这点与 oracle 不同,oracle 需要在创建库时就创建好连续的磁盘空间作为表空间),因此 innodb 类型表的访问速度取决于你的硬盘碎片的程度。碎片越多,速度越慢
楼主求真相的精神真让我感动。这个问题我也仔细想过,如果只使用内存,感觉使用哈希是最好了。但如果使用硬盘,控制内存。大量的io就成了主要矛盾,mysql就是这样
既然你已经有数据了,帮试下。重新建索引的时间是多少。如果超过10分钟就不用再试了。
建索引就生成了索引文件,是一个真正的排序过程。mysql是使用b+树结构,随着树的深度,以后定位数据花的时间会越来越多。因此索引文件生成会越来越慢。估计不太乐观。至于innodb的索引就不用考虑了。
innodb 表测试
set_time_limit(0);$sql =<<< sqlcreate table if not exists qq2 ( `qq` int(10) not null, key `qq` (`qq`)) engine=innodb default charset=utf8;sql;mysql_connect('localhost', 'root', '');mysql_select_db('test');mysql_query($sql);echo '导入
';$filename = str_replace('\\', '/', realpath('qq.txt'));$sql =<<< sqlload data infile '$filename' into table qq2sql;check_speed(1);mysql_query($sql) or print(mysql_error());;check_speed();
导入
时间: 3,286,588,777 微秒
内存: 664
导出
set_time_limit(0);mysql_connect('localhost', 'root', '');mysql_select_db('test');echo '升序
';$filename = str_replace('\\', '/', dirname(__file__) . '/qq_1.txt');if(file_exists($filename)) unlink($filename);$sql =<<< sqlselect qq from qq2 order by qq asc into outfile '$filename'sql;check_speed(1);mysql_query($sql) or print(mysql_error());check_speed();echo '降序
';$filename = str_replace('\\', '/', dirname(__file__) . '/qq_2.txt');if(file_exists($filename)) unlink($filename);$sql =<<< sqlselect qq from qq2 order by qq desc into outfile '$filename'sql;check_speed(1);mysql_query($sql) or print(mysql_error());check_speed();echo '主键不排序
';$filename = str_replace('\\', '/', dirname(__file__) . '/qq_0.txt');if(file_exists($filename)) unlink($filename);$sql =<<< sqlselect qq from qq2 into outfile '$filename'sql;check_speed(1);mysql_query($sql) or print(mysql_error());;check_speed();
升序
时间: 367,638,625 微秒
内存: 520
降序
时间: 390,232,528 微秒
内存: 432
主键不排序
时间: 367,762,026 微秒
内存: 432
ok, 又试了全是11位的qq号, 实际上100020001个,
sort一下, 22分钟
引用 12 楼 ci1699 的回复:
这位同学请教一下,直接sort怎么弄啊?
引用 6 楼 helloyou0 的回复:
用你代码生成qq.txt,
然后直接sort,
在我的fedora(vmware)里18分钟出结果
(可能还要短一点,因为我把它放后台了)
就是unix的命令sort啊
改天我再试试大点的文件和mysql数据库
仅给出测试的时间是没有意义的,因为同一代码在不同的机器和操作系统中,执行的效果并不取决于算法和代码本身
不同的算法和代码在同一环境中运行,才能体现出优劣
原来还可以这么导啊。
我刚执行了下,
用了387.14144778252。
这下又导入又有索引了。
看样子还是用上索引哈。。
既然有现成的数据文件,就没有必要去构造插入串了
php code
set_time_limit(0);
$sql =>shift]|(1shift]=a[n>>shift]&(~(1shift] & (1<<(n&mask)); }int main(int argc, char *argv[]){ int i; int tp; file *ip; file *op; for(i=1;i<=max;i++) { clear(i); } ip = fopen(qq_before_sort.txt,r); while( !feof(ip) ) { fscanf(ip,%d\n,&tp); set(tp); } fclose(ip); op = fopen(qq_after_sort.txt,w); for(i=1;i<=max;i++) { if(test(i)){ fprintf(op, %d\n,i); } } fclose(op); return 0;}
在次看过,忙完了,在来学习
c
程序快这么多
????
主贴的qq号默认最大是100009999,而目前可能的最大qq号却是9999999999,差好多个数量级呢,实际情况使用位排序就是 9999999999 /8 /1024 /1024 差不多1.1g内存。。。
用主贴生成的数据测试了下,机器比较烂,花了300多秒生成,用c实现的位排序法读,排,写,总共时间差不多1分10秒多,lz可以拿去测试看看,对了,主贴中生成qq号我改成了1行一个qq,方便……
为什么编译不过去。。
错误 qq.c 7: 数组太小
主贴的qq号默认最大是100009999,而目前可能的最大qq号却是9999999999,差好多个数量级呢,实际情况使用位排序就是 9999999999 /8 /1024 /1024 差不多1.1g内存。。。
用主贴生成的数据测试了下,机器比较烂,花了300多秒生成,用c实现的位排序法读,排,写,总共时间差不多1分10秒多,lz可以拿去测试看看,对了,主贴中生成qq号我改成了1行一个qq,方便……
其它类似信息

推荐信息