解决PHP里大量数据循环时内存耗尽的方法


Posted in PHP onOctober 10, 2015

最近在开发一个PHP程序的时候遇到如下一问题:

PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted

错误信息显示允许的最大内存已经耗尽。遇到这样的错误起初让我很诧异,但转眼一想,也不奇怪,因为我正在开发的这个程序是要用一个foreach循环语句在一个有4万条记录的表里全表搜索具有特定特征的数据,也就是说,一次要把4万条数据取出,然后逐条检查每天数据。可想而知,4万条数据全部加载到内存中,内存不爆才怪。

 解决PHP里大量数据循环时内存耗尽的方法

毕竟编程这么多年,我隐约记得PHP里提供有非一次全部加载数据的API,是像处理流媒体那样,随用随取随丢、数据并不会积累在内存的查询方法。经过简单的搜索,果然在官方网站上找到的正确的用法。

这个问题在PHP的官方网站上叫缓冲查询和非缓冲查询(Buffered and Unbuffered queries)。 PHP的查询缺省模式是缓冲模式。也就是说,查询数据结果会一次全部提取到内存里供PHP程序处理。这样给了PHP程序额外的功能,比如说,计算行数,将 指针指向某一行等。更重要的是程序可以对数据集反复进行二次查询和过滤等操作。但这种缓冲查询模式的缺陷就是消耗内存,也就是用空间换速度。

相对的,另外一种PHP查询模式是非缓冲查询,数据库服务器会一条一条的返回数据,而不是一次全部返回,这样的结果就是PHP程序消耗较少的内存,但却增加了数据库服务器的压力,因为数据库会一直等待PHP来取数据,一直到数据全部取完。

很显然,缓冲查询模式适用于小数据量查询,而非缓冲查询适应于大数据量查询。

对于PHP的缓冲模式查询大家都知道,下面列举的例子是如何执行非缓冲查询API。

非缓冲查询方法一: mysqli

<?php 
$mysqli = new mysqli("localhost", "my_user", "my_password", "world"); 
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT); 
if ($uresult) { 
  while ($row = $uresult->fetch_assoc()) { 
    echo $row['Name'] . PHP_EOL; 
  } 
} 
$uresult->close(); 
?>

非缓冲查询方法二: pdo_mysql

<?php 
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass'); 
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 

$uresult = $pdo->query("SELECT Name FROM City"); 
if ($uresult) { 
  while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) { 
    echo $row['Name'] . PHP_EOL; 
  } 
} 
?>

非缓冲查询方法三: mysql

<?php 
$conn = mysql_connect("localhost", "my_user", "my_pass"); 
$db  = mysql_select_db("world"); 

$uresult = mysql_unbuffered_query("SELECT Name FROM City"); 
if ($uresult) { 
  while ($row = mysql_fetch_assoc($uresult)) { 
    echo $row['Name'] . PHP_EOL; 
  } 
} 
?>

以上内容就是小编给大家分享的解决PHP里大量数据循环时内存耗尽的方法,希望对大家有所帮助。

PHP 相关文章推荐
JAVA/JSP学习系列之二
Oct 09 PHP
php侧拉菜单 漂亮,可以向右或者向左展开,支持FF,IE
Oct 15 PHP
如何使用Linux的Crontab定时执行PHP脚本的方法
Dec 19 PHP
php去除换行符的方法小结(PHP_EOL变量的使用)
Feb 16 PHP
简单的cookie计数器实现源码
Jun 07 PHP
请离开include_once和require_once
Jul 18 PHP
php中PDO方式实现数据库的增删改查
May 17 PHP
深入解析PHP中foreach语句控制数组循环的用法
Nov 30 PHP
PHP实现将多个文件压缩成zip格式并下载到本地的方法示例
May 23 PHP
Laravel 读取 config 下的数据方法
Oct 13 PHP
php装饰者模式简单应用案例分析
Oct 23 PHP
php文件上传原理与实现方法详解
Dec 20 PHP
php中删除、清空session的方式总结
Oct 09 #PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
Oct 09 #PHP
PHP中Closure类的使用方法及详解
Oct 09 #PHP
如何解决phpmyadmin导入数据库文件最大限制2048KB
Oct 09 #PHP
PHP程序员不应该忽略的3点
Oct 09 #PHP
PHP+jQuery+Ajax实现分页效果 jPaginate插件的应用
Oct 09 #PHP
jQuery+Ajax+PHP“喜欢”评级功能实现代码
Oct 08 #PHP
You might like
php数据库连接时容易出错的特殊符号问题
2010/09/01 PHP
神盾加密解密教程(一)PHP变量可用字符
2014/05/28 PHP
destoon实现VIP排名一直在前面排序的方法
2014/08/21 PHP
php短址转换实现方法
2015/02/25 PHP
详谈配置phpstorm完美支持Codeigniter(CI)代码自动完成(代码提示)
2017/04/07 PHP
Aster vs KG BO3 第三场2.19
2021/03/10 DOTA
JS类定义原型方法的两种实现的区别评论很多
2007/09/12 Javascript
Array, Array Constructor, for in loop, typeof, instanceOf
2011/09/13 Javascript
jQuery中:first-child选择器用法实例
2014/12/31 Javascript
js运动应用实例解析
2015/12/28 Javascript
jQuery的promise与deferred对象在异步回调中的作用
2016/05/03 Javascript
基于jQuery下拉选择框插件支持单选多选功能代码
2016/06/07 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
Bootstrap CSS布局之表格
2016/12/17 Javascript
JavaScript正则表达式校验与递归函数实际应用实例解析
2017/08/04 Javascript
实例详解JSON取值(key是中文或者数字)方式
2017/08/24 Javascript
vue.js  父向子组件传参的实例代码
2017/10/29 Javascript
Bootstrap4如何定制自己的颜色和风格
2018/02/26 Javascript
解决vue attr取不到属性值的问题
2018/09/18 Javascript
Vue 实现一个命令式弹窗组件功能
2019/09/25 Javascript
Vue实现渲染数据后控制滚动条位置(推荐)
2019/12/09 Javascript
微信小程序收藏功能的实现代码
2020/06/19 Javascript
Javascript数组及类数组相关原理详解
2020/10/29 Javascript
[00:56]2014DOTA2国际邀请赛 DK、iG 赛前探访
2014/07/10 DOTA
python调用matlab的m自定义函数方法
2019/02/18 Python
Python使用pyautocad+openpyxl处理cad文件示例
2019/07/11 Python
详解有关PyCharm安装库失败的问题的解决方法
2020/02/02 Python
如何使用Python进行PDF图片识别OCR
2021/01/22 Python
美国领先的个性化礼品商城:Personalization Mall
2019/07/27 全球购物
院药学专业个人求职信
2013/09/21 职场文书
建筑行业的大学生自我评价
2013/12/08 职场文书
中小学生学籍证明
2014/10/25 职场文书
解除劳动合同证明书模板
2014/11/20 职场文书
2015中学学校工作总结
2015/07/20 职场文书
宾馆安全管理制度
2015/08/06 职场文书
MongoDB连接数据库并创建数据等使用方法
2021/11/27 MongoDB