解决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 相关文章推荐
完美实现GIF动画缩略图的php代码
Jan 02 PHP
PHP性能优化准备篇图解PEAR安装
Dec 05 PHP
深入PHP5中的魔术方法详解
Jun 17 PHP
PHP中substr()与explode()函数用法分析
Nov 24 PHP
php+jQuery.uploadify实现文件上传教程
Dec 26 PHP
php解析url并得到url中的参数及获取url参数的四种方式
Oct 26 PHP
4种PHP异步执行的常用方式
Dec 24 PHP
php使用crypt()函数进行加密
Jun 08 PHP
解决出现SoapFault (looks like we got no XML document)的问题
Jun 24 PHP
PHP十六进制颜色随机生成器功能示例
Jul 24 PHP
PHP 实现手机端APP支付宝支付功能
Jun 07 PHP
PHP中的empty、isset、isnull的区别与使用实例
Mar 22 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实现ping
2006/10/09 PHP
PHP面向对象法则
2012/02/23 PHP
PHP 万年历实现代码
2012/10/18 PHP
PHP实现删除非站内外部链接实例代码
2014/06/17 PHP
PHP源码分析之变量的存储过程分解
2014/07/03 PHP
ThinkPHP数据操作方法总结
2015/09/28 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
JavaScript 拾碎[三] 使用className属性
2010/10/16 Javascript
如何用js控制frame的隐藏或显示的解决办法
2013/03/20 Javascript
Javascript中的for in循环和hasOwnProperty结合使用
2013/06/05 Javascript
使用js正则控制input标签只允许输入的值
2013/07/29 Javascript
Jquery中children与find之间的区别详细解析
2013/11/29 Javascript
jquery插件lazyload.js延迟加载图片的使用方法
2014/02/19 Javascript
JSON.parse()和JSON.stringify()使用介绍
2014/06/20 Javascript
jQuery禁用键盘后退屏蔽F5刷新及禁用右键单击
2016/01/22 Javascript
JavaScript实现弹出DIV层同时页面背景渐变成半透明效果
2016/03/25 Javascript
基于JS实现数字+字母+中文的混合排序方法
2016/06/06 Javascript
全面了解JS中的匿名函数
2016/06/29 Javascript
AngularJS基础 ng-cut 指令介绍及简单示例
2016/08/01 Javascript
JS打开摄像头并截图上传示例
2017/02/18 Javascript
javascript实现日期三级联动下拉框选择菜单
2020/12/03 Javascript
jquery实现简单实用的轮播器
2017/05/23 jQuery
OkHttp踩坑随笔为何 response.body().string() 只能调用一次
2018/01/08 Javascript
JavaScript写个贪吃蛇小游戏(超详细)
2020/03/17 Javascript
vue tab切换,解决echartst图表宽度只有100px的问题
2020/07/19 Javascript
JavaScript数组排序的六种常见算法总结
2020/08/18 Javascript
[51:11]2014 DOTA2国际邀请赛中国区预选赛5.21 LGD-CDEC VS DT
2014/05/22 DOTA
Python根据指定日期计算后n天,前n天是哪一天的方法
2018/05/29 Python
记录Python脚本的运行日志的方法
2019/06/05 Python
Python产生一个数值范围内的不重复的随机数的实现方法
2019/08/21 Python
使用Python pip怎么升级pip
2020/08/11 Python
浅谈html5 响应式布局
2014/12/24 HTML / CSS
英国马莎百货官网:Marks & Spencer
2016/07/29 全球购物
促销活动总结
2014/04/28 职场文书
Redis如何一键部署脚本
2021/04/12 Redis
OpenCV-Python实现油画效果的实例
2021/06/08 Python