解决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 相关文章推荐
PHP,ASP.JAVA,JAVA代码格式化工具整理
Jun 15 PHP
简单的cookie计数器实现源码
Jun 07 PHP
基于php中使用excel的简单介绍
Aug 02 PHP
Codeigniter生成Excel文档的简单方法
Jun 12 PHP
PHP实现自动登入google play下载app report的方法
Sep 23 PHP
php制作动态随机验证码
Feb 12 PHP
php批量删除超链接的实现方法
Oct 19 PHP
9个比较实用的php代码片段
Mar 15 PHP
PHP数组编码gbk与utf8互相转换的两种方法
Sep 01 PHP
php基于Redis消息队列实现的消息推送的方法
Nov 28 PHP
PHP正则验证字符串是否为数字的两种方法并附常用正则
Feb 27 PHP
PHP RabbitMQ消息列队
May 11 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
图形数字验证代码
2006/10/09 PHP
PHP下载生成的csv文件及问题总结
2015/08/06 PHP
用javascript实现画板的代码
2007/09/05 Javascript
JavaScript高级程序设计 事件学习笔记
2011/09/10 Javascript
cnblogs 代码高亮显示后的代码复制问题解决实现代码
2011/12/14 Javascript
JS编程小常识很有用
2012/11/26 Javascript
Jquery实现页面加载时弹出对话框代码
2013/04/19 Javascript
js实现表格字段排序
2014/02/19 Javascript
原生js实现图片轮播特效
2015/12/18 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
2016/07/15 Javascript
Vue实例简单方法介绍
2017/01/20 Javascript
JS中使用 after 伪类清除浮动实例
2017/03/01 Javascript
Angular整合zTree的示例代码
2018/01/24 Javascript
微信小程序中时间戳和日期的相互转换问题
2018/07/09 Javascript
详解如何在微信小程序中愉快地使用sass
2018/07/30 Javascript
react native 原生模块桥接的简单说明小结
2019/02/26 Javascript
微信小程序canvas截取任意形状的实现代码
2020/01/13 Javascript
JavaScript 中判断变量是否为数字的示例代码
2020/10/22 Javascript
详解JavaScript之Array.reduce源码解读
2020/11/01 Javascript
对django中render()与render_to_response()的区别详解
2018/10/16 Python
Python实现性能自动化测试竟然如此简单
2019/07/30 Python
利用python实现冒泡排序算法实例代码
2019/12/01 Python
Html5移动端div固定到底部实现底部导航条的几种方式
2021/03/09 HTML / CSS
Spartoo芬兰:欧洲最大的网上鞋店
2016/08/28 全球购物
瑞典手机壳品牌:Richmond & Finch
2018/04/28 全球购物
2013年入党人员的自我鉴定
2013/10/25 职场文书
自我鉴定 电子商务专业
2014/01/30 职场文书
星级党支部申报材料
2014/05/31 职场文书
企业爱岗敬业演讲稿
2014/09/04 职场文书
花田少年史观后感
2015/06/16 职场文书
2016特色励志班级口号
2015/12/24 职场文书
PHP实现rar解压读取扩展包小结
2021/06/03 PHP
忆童年!用Python实现愤怒的小鸟游戏
2021/06/07 Python
用Java实现简单计算器功能
2021/07/21 Java/Android
redis数据结构之压缩列表
2022/03/21 Redis
JavaScript实现音乐播放器
2022/08/14 Javascript