面试中经常会遇到一些面试官问 ,百万级别的数据中,如何快速查找到这个数是否存在?
如何来进行存储?
下面我们来做一个测试
首先创建一个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
试问: 读取哪个文件快?