面试问题:给你一个文本文件,里面存储了一亿个QQ号,请用程序将其由小到大排序,汗呀!..
求高手讲解思路!
还有其它问题:
比如Memcache的运行机制,它的工作原理它有什么优缺点!
现有一个库存100件的产品要进行秒杀,在秒杀过程中的秒杀人数远远超过库存,请问你将如何处理,应该注意什么问题!
请谈谈你对Mysql的优化的见解,或者说如果让你设计一个数据库,你将怎样设计并优化!
有高手吗,今天面试都自己认为都答得不太理想,求指教,还有下面的面试!
小弟的刚刚被裁员,本来就冬天,真的好冷啊!
求高手讲解思路!
还有其它问题:
比如Memcache的运行机制,它的工作原理它有什么优缺点!
现有一个库存100件的产品要进行秒杀,在秒杀过程中的秒杀人数远远超过库存,请问你将如何处理,应该注意什么问题!
请谈谈你对Mysql的优化的见解,或者说如果让你设计一个数据库,你将怎样设计并优化!
有高手吗,今天面试都自己认为都答得不太理想,求指教,还有下面的面试!
小弟的刚刚被裁员,本来就冬天,真的好冷啊!
如果都不限制直接sort函数就行,里面是用的快速排序法(quicksort),理论上的效率应该是最高的,况且人家是native code,怎么也比php代码里模拟一个排序算法快。memcache的运行机制是使用职守进程开辟一块内存空间用来保存key/value数据,所有的请求和应用都共用这些数据。优点是存取速度快,适合用来缓存频繁读写的数据。缺点是占用内存,同时只能通过key检索,无法进行关系查询(SQL等)。要保证原子操作,使用一定的锁机制防止多个请求同时操作一个数据造成效果与预期不符。mysql数据库优化主要是索引和分表,为了性能可以为所有需要排序和检索的字段建立索引,并通过水平或垂直分表方式提高效率。
因为平均时间和快速排序归并排序一样是O(nlogn)辅助存储是O(1)如果你只是需要单纯地记录一个QQ号而不包含其用户信息的话
目前常用的排序算法都是以内存为载体的,既然不能全部加载,那么排序算法也就不能用了于是可选择 哈希表 与 文件操作
创建一个文件作为 QQ表的索引:
以 QQ 号(转换成长整形)为偏移,存放 1 个字节的标志创建完成后,顺次读取索引文件,每次一字节。如果标志置位则其偏移就是 QQ 号,写入新文件即可代码省略,请自行书写。
作为面试,有思路就可以的
光是那个文件就差不多1G了,全部载入内存似乎是不现实
遍历一遍,将号码按大小,写入合适的文件比如约定10万一个号码段比如10,000,写在第0个文件,100,000,001,属于第1K个文件里面排序每一个文件数据,拼接文件排序的时候,如果文件较大,这里根据文件大小,大概能估计号码数量级的。。如果号码量少,可选择快排,否则,创建一个10万的数组,再次遍历,arr[qqnum-i*100000]+1;遍历数组,依数组值,增量写入号码即可复杂度是O(n),O(nlogn)之间
如果想研究算法及数据结构的可以去找找资料.
===============================================
请求直接推入队列,再开一个程序读取队列,一条条处理。linux下php可直接调用系统队列(msg_前缀)请谈谈你对Mysql的优化的见解,或者说如果让你设计一个数据库,你将怎样设计并优化!
==============================================================================
哥就会dbdesigner建模,测试环境打开slow query log,explain观察
不过这个代码在实现上有点问题,目前 QQ号已经到达10位了仅存储这个串就需要 1G 内存。
$s = '0';//5-7位的
$s2 = '0';//7-10位的$s2{qq号 - 1000000} = 1;
那么建一个10^11bit的文件(理论上内存也可以),遍历保存有QQ号的文本文件,将每个QQ号对应的第n位bit置为1。然后顺序遍历这个文件,如果第n位为1则输出QQ号,理论上可以达到O(n)的复杂度。
7 - 8位q一个文件,8 - 10位一个文件,然后每一位再加上每个文件bit位表示特定的偏移量。
0000000000 ~ 9999999999如果真到了 10G,其实只要到达 2G,34位系统就都无法处理了php 所谓整数是 有符号 logn 类型的, 正数的上限是 2G - 1
就打算你把它当做无符号整数处理(假定操作系统也支持),其上限也只是 4G - 1
你算的是纯二进制位,不能说错,但是实现起来可能比较麻烦,就好象一个整形数999999,把其二进制第x位设置为1,然后最终结果还是得转二进制,找里面的1的位置。
而我们上面讨论是直接用串来表示二进制位,即一个字节为表示1位,(9999999999-9999)/(1024*1024*1024)大概9G多。
编程的方法入库,用算法排
是用的位图
举个例子吧! 会php的请尽量贴代码!
原理未变,只是将按字节操作改为按位操作$num = 数;
$n = $num >> 3;
$m = 1 << $n % 8;
$s{$n} |= $m;只不过 10^9 /8 /1024 /1024 ,只要100M内存 这样才 9 位号码,并不能覆盖所有的 QQ 号
又找了一下,这个免费http://download.csdn.net/download/xkjack/2096200从事计算机应用普及二十年,现已退休三年了
嗯,实际不需要这么多,因为这个数组可以是布尔型,这样1位可以放32个,实际空间只需要6M。嗯嗯,把读到的号码对应的位标成true,读取时遇到值为true的输出其下标。
我觉得还是根据qq号hash到多个小文件里,然后对小文件里的号码快速排序,然后在多路归并排序好点。
http://archive.cnblogs.com/a/2217369/
$n = $num >> 3;
$m = 1 << $n % 8; 这里应该是 $m % 8
$s{$n} |= $m;一个位的信息只能存2种状态,,,一般这种题,应该会说明数据并不会重复,或者如前面说的,只给你限定的内存如果数据有重复,还是要靠数组来解决吧,
他按 long 算 一个 long 占 4 个字节,共 32 个二进制位
不是一样吗?
用sqlldr 在nologing的模式下导入,比较快。
过程中根据规则设定50个分区,每个平均200W记录,按分区顺序分别排序导出
其实24楼和77楼的方法都可行,不用编程......
不过这分别是sysadmin和DBA的方法, 其它回帖都属于程序员的方法啦.....
define('TOTALS_NUMS',20);
define('NUM_START',500);
bitsort(randNum(MAX_NUM,NUM_START,TOTALS_NUMS));
function bitsort($data){
$len = strlen(MAX_NUM);
$n = ceil((10^$len-1)/32);//位标识数组长度
$a = array_fill(1,$n,0);//位标识数组
echo '<br><br><br>';
for($i=0;$i<TOTALS_NUMS;++$i){
$a[intval($data[$i]/32)+1] |=1<<($data[$i]-1);//将标识位置为1
}
for($i=1;$i<=MAX_NUM;++$i){
for($j=0;$j<32;++$j){
$tmp = (1<<$j);
if(($a[$i]&$tmp)!=0){
echo (($i-1)*32+$j).'--<br>';
}
}
}
}
//随机生成start-n中的k个不重复的数
function randNum($p_n,$p_start,$p_k){
if($p_start>=$p_n)
return false;
for($i = $p_start;$i<=$p_n;++$i){
$a[$i] = $i;
}
for($j = 1;$j<=$p_k;++$j){
$r = mt_rand($p_start+$j,$p_n);
$b[] = $a[$r];
$a[$r] = $a[$p_start+$j];
}
return $b;
}
这就是理论与实践的差别
也是小规模数据和大规模数据的差别
所以软件工程学中一再强调边界数据的测试我用set_time_limit(0);
$fn = 'qq.txt';
echo microtime(true);
$a = range(0, 19999);
$b = range(0, 99999);
shuffle($a);
shuffle($b);$fp = fopen($fn, 'w');
for($i=0; $i<count($a); $i++)
for($j=0; $j<count($b); $j++)
fprintf($fp, "%d%05d%s", $a[$i], $b[$j], PHP_EOL);
fclose;
echo PHP_EOL, microtime(true);创建一个测试数据文件
结果耗时近 6 个小时得到一个 21G 的文件机器参数
Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz
3.09 GHz 1.98 GB 内存
操作系统 XP于是我决定放弃了,这种无聊的工作不是 php 可干的
echo microtime(true);$a = range(0, 10000);
$b = range(0, 10000);
shuffle($a);
shuffle($b);$buffer = '';$fp = fopen($fn, 'a+');
for($i=0,$n=count($a); $i<$n; ++$i)
for($j=0,$m=count($b); $j<$m; ++$j){
$buffer .= sprintf("%d%05d%s", $a[$i], $b[$j], PHP_EOL);
if($j === $m-1){
fwrite($fp, $buffer);
$buffer = '';
}
}
fclose($fp);
echo PHP_EOL, microtime(true);
847 MB (888,330,999 字节)但这么大的文件php怎么读。纠结中。
什么都关了。给最大内存依然读不了文件。
$t = microtime(true);
$s = ' ';
for($i=0; $i<100000000; $i++) {
$s{$i} = 'a';
}
echo microtime(true) - $t;
18.607635974884按位存储
set_time_limit(0);
$t = microtime(true);
$s = ' ';
for($i=0; $i<100000000; $i++) {
$p = $i >> 3;
for($m=1; $m<=128; $m <<= 1)
$s{$p} = chr(ord($s{$p}) | $m);
}
echo microtime(true) - $t;
583.47053003311
而且真要实现什么的就不要想着用php了吧,直接底层c了,php是高级语言,内存管理对于php来说是透明的,同样是一个integer变量,对c和对php来说意义完全不一样的,php的变量值存储就是一个c的结构体(Zval),因为php是弱类型,Zval内部的value又是一个结构体,所以Zval实际占的字节数可就多的多了
例如QQ号码:12345678,可以放到123区的第45678的位置,这样遍历一遍QQ号码后,所有的QQ号码就排好序了。