昨天做了个实验,一次插入20万条数据,毫无疑问,这会做成了php的内出溢出,如下
Fatal error: Allowed memory size of 134217728 bytes exhausted
简单点就是内存中的东西太多了,超过php配置的最高承受,要解决要么就把配置调高,要么就是分批插入,用完的变量从内出中清空。
基本实现思路如下:
for ($k=0;$k<20;$k++){
$dataList = [];
for($i=0;$i<10000;$i++){
$dataList[] = [name => "321" , test => uniqid("tp_",true)];
}
dump(M("test") ->addAll($dataList));
$dataList = null;//每次插入后就清空
echo M("test")->count();
echo "完成$k 次 \n";
}
至于为什么用等于 null 而不是 unset,其实unset只不过是清除引用,并不是清除内存中值,只有当那个值得引用为0时,才会被php垃圾回收机制回收,所以防止值还有其他引用,就选用 = null会比较好,当然,上面例子unset也可以、
但发现还是不可以,把内存打印出来看看
for ($k=0;$k<20;$k++){
$dataList = [];
for($i=0;$i<10000;$i++){
$dataList[] = [name => "321" , test => uniqid("tp_",true)];
}
$m=memory_get_usage();//当前内存
//
dump(M("test") ->addAll($dataList));
// dump(M("test") ->getLastSql());
$dataList = null;
$mm=memory_get_usage();//清空后内存
echo $m-$mm." ---------->".M("test")->count();
echo "完成$k 次 \n";
}
string(6) "182306"
-605856 ---------->191603完成14 次
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 640000 bytes) in E:\workspace\app\ThinkPHP\Library\Think\Db\Driver.class.php on line 198
Call Stack:
0.0000 227704 1. {main}() E:\workspace\app\index.php:0
-605856 证明内存并没有很好的清除,原因是我这里用了thankphp 3.2 框架,它在内部定义了许多的变量,而这些变量我又不能到其源码中进行 set null,所以只能用原生函数,改如下:
$con = mysql_connect("localhost","root","J_123456");
mysql_select_db("test", $con);
for ($k=0;$k<20;$k++){
$dataList = [];
$sqlstr = "";
for($i=0;$i<10000;$i++){
$dataList[] = "('321',".uniqid("'tp_",true)."')";//[name => "321" , test => uniqid("tp_",true)];
}
$sqlstr = implode(",",$dataList);
$m=memory_get_usage();//当前内存
//
$sqlstr = "INSERT INTO `test` (`name`,`test`) VALUES ".$sqlstr;
// dump(M("test") ->addAll($dataList));
dump(mysql_query($sqlstr));
dump(mysql_error());
$dataList = null;
$sqlstr = null;
$mm=memory_get_usage();//清空后内存
echo $m-$mm." ---------->".M("test")->count();
echo "\n ok $k 's \n";
}
这次就能快速插入20W 数据了。
关于php 内存,这里记录一下
$a = str_repeat('1',256);//这里尽量大点,主要看正负,毕竟引用也是占用内出的
$b = &$a;
$c = &$a;
$m=memory_get_usage();//当前内存
unset($a);
unset($b);
// unset($c);//unset 必须a,b,c 都同时执行了才回收他们对应的值,才会释放内存
// $c = null;//无论 a,b,c 随便一个set null了都会回收
$mm=memory_get_usage();//清空后内存
echo $m-$mm;
return;