最近有客户想一次性把客户的客资数据导出备份,经过几年的使用,很多客户的客资量都接近百万,如果要一次性导出这么多量,就不能直接从数据库读取放到数组里面,一个是 php 默认会限制内存使用量,另外内存也不应该浪费在这个上面。
Yii 框架提供了 BatchQueryResult
对象,该对象实现了 Iterator
接口,这样从数据库获取数据不会受限于内存,影响系统的稳定了。
环境说明:PHP 7.2
$unbufferedDb = new \yii\db\Connection([
'dsn' => Yii::$app->pc->dsn,
'username' => Yii::$app->pc->username,
'password' => Yii::$app->pc->password,
'charset' => Yii::$app->pc->charset,
]);
$unbufferedDb->open();
$unbufferedDb->pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$query = Leads::find()->all();
foreach ($query->each(50, $unbufferedDb) as $item) {
// 这里就可以一个个处理数据(还原中文显示,其他关联的数据)并写入文件中
}
每次遍历 50 个客资进行处理,关于 $unbufferedDb
,Yii 官方文档也有说明(p1),测试下来把 MYSQL_ATTR_USE_BUFFERED_QUERY
设置为 false
,内存使用量才是正常的。
[图片:p1]
[图片:p2]
[图片:p3]
图片 p2 和 p3 分别是导出时的进程,MYSQL_ATTR_USE_BUFFERED_QUERY
分别为 false
和 true
,通过 memory_get_usage
函数内存占用基本相同,但看进程内存占用是不一样的,一个 0.5%、一个 6%。
Yii 文档里面提到的 libmysqlclient
库,php 5.4 之后编译时默认改成了 mysqlnd
。