面试中经常会遇到一些面试官问 ,百万级别的数据中,如何快速查找到这个数是否存在?
如何来进行存储?
下面我们来做一个测试
首先创建一个150万的数据
data.txt 这是一个字符串数据,共计 150 万个数据,大小共计 10.3M
那么我们先看看这么大的数据范围内,如何判断文件是否在数组中:
我这里提供了两种方法,是我自己想想的,请大家看看:
1、把数组进行val排序 sort($data) 然后 key、value 交换位置 ,最后适用isset()判断数据是否存在
2、采用位图法,首先将数组进行bitmap 位图化,然后进行查找
先来看看第一种方法:
1、排序 进行数据判断是否存在
A、读取文件数据 并以逗号进行分割
B、sort进行数据排序
C、isset() 是否存在
代码如下:
ini_set('memory_limit', '1000M'); $findval = 1000004; printf("开始内存使用情况:%s M\n", bcdiv(memory_get_usage(), 1024 * 1024, 3)); $starttime = microtime(true); $data = explode(',', file_get_contents('data.txt')); sort($data); // $bitmap = bitmap($data); $data = array_flip($data); if (isset($data[$findval])) { printf("findVal:%s 存在\n", $findval); } $howtime = bcsub(microtime(true), $starttime, 3); printf("总共耗时:%s \n", $howtime); printf("内存使用情况:%s M\n", bcdiv(memory_get_usage(), 1024 * 1024, 3));
使用内存排序法,内存占用情况,及结果
有时,还极易出一内存溢出等问题:这是不能容忍的,所以使用这种方法,请设置内存大小
结论:
这样的方法 总共耗时 2.127 秒 内存使用情况是 56M
2、位图法
位图法,我这里提供了三张图,运行时间差不多,程序使用内存出现了极大的不同,
我们先来看看第一种方法:
改良后的内存使用情况:
发生了什么?为什么会内存适用情况会发生这么大的变化?
看上面的红字
使用2M内存
$bitmap = bitmap(explode(',', file_get_contents('data.txt')));
使用 86M 内存
$data = explode(',', file_get_contents('data.txt'));
$bitmap = bitmap($data);
以上功能是一样的,这也许就是高级程序员与初级程序员的区别吧
printf("开始内存使用情况:%s M\n", bcdiv(memory_get_usage(), 1024 * 1024, 3)); $starttime = microtime(true); // $bitmap = bitmap(explode(',', file_get_contents('data.txt'))); $data = explode(',', file_get_contents('data.txt')); $bitmap = bitmap($data); $howtime = bcsub(microtime(true), $starttime, 3); printf("是否包含1000004:%s \n", checkExists($bitmap, 1000004) ? '是' : '否'); printf("总共耗时:%s \n", $howtime); printf("内存使用情况:%s M\n", bcdiv(memory_get_usage(), 1024 * 1024, 3));
结论:
以上的这两种判断方法还是很快的,
我推荐使用位图法 时间是 1.3秒 内存适用2M多,这对于服务器来说是很快的
排序查找法 时间是 2.1秒 内存适用情况是 56M多 ,足足慢了快1秒了 内存使用 是位图法的 28倍 ,由此可见 位图法 对于大数据存储与查找速度还是很快的。
总比 foreach 循环快多了吧!呵呵呵
保存成位图来说:
一个是10M多 一个是 600多K 还不到1M
试问: 读取哪个文件快?