解决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 相关文章推荐
第七节 类的静态成员 [7]
Oct 09 PHP
人大复印资料处理程序_查询篇
Oct 09 PHP
用session做客户验证时的注意事项
Oct 09 PHP
PHP判断远程url是否有效的几种方法小结
Oct 08 PHP
php中拷贝构造函数、赋值运算符重载
Jul 25 PHP
php调用c接口无错版介绍
Mar 11 PHP
php中curl、fsocket、file_get_content三个函数的使用比较
May 09 PHP
PHP不用递归遍历目录下所有文件的代码
Jul 04 PHP
简单介绍win7下搭建apache+php+mysql开发环境
Aug 06 PHP
为何说PHP引用是个坑,要慎用
Apr 02 PHP
PHP的mysqli_sqlstate()函数讲解
Jan 23 PHP
Thinkphp5框架实现获取数据库数据到视图的方法
Aug 14 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模拟post提交数据的方法
2015/02/12 PHP
php保存信息到当前Session的方法
2015/03/16 PHP
微信公众号模板消息群发php代码示例
2016/12/29 PHP
laravel框架数据库操作、查询构建器、Eloquent ORM操作实例分析
2019/12/20 PHP
JS 面向对象之神奇的prototype
2011/02/26 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
2013/11/17 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
2014/10/17 Javascript
Bootstrap框架下下拉框select搜索功能
2020/03/26 Javascript
仿百度换肤功能的简单实例代码
2016/07/11 Javascript
Angularjs 创建可复用组件实例代码
2016/10/09 Javascript
jquery实现轮播图效果
2017/02/13 Javascript
JS滚动到指定位置导航栏固定顶部
2017/07/03 Javascript
js实现unicode码字符串与utf8字节数据互转详解
2019/03/21 Javascript
package.json配置文件构成详解
2019/08/27 Javascript
React Native 混合开发多入口加载方式详解
2019/09/23 Javascript
[01:13:01]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第三场
2018/04/05 DOTA
Python3.x和Python2.x的区别介绍
2013/02/12 Python
Python生成随机密码
2015/03/10 Python
python threading模块操作多线程介绍
2015/04/08 Python
Python标准库06之子进程 (subprocess包) 详解
2016/12/07 Python
django框架使用orm实现批量更新数据的方法
2019/06/21 Python
python实现将range()函数生成的数字存储在一个列表中
2020/04/02 Python
一些关于python 装饰器的个人理解
2020/08/31 Python
Python Tkinter实例——模拟掷骰子
2020/10/24 Python
史泰博(Staples)中国官方网站:办公用品一站式采购
2016/09/05 全球购物
Puritan’s Pride(普丽普莱)官方网站:美国最大最全的保健品公司之一
2016/10/23 全球购物
荷兰演唱会和体育比赛订票网站:viagogo荷兰
2018/04/08 全球购物
Lookfantastic日本官网:英国知名护肤、化妆品和头发护理购物网站
2018/04/21 全球购物
Currentbody美国/加拿大:美容仪专家
2020/03/09 全球购物
《夸父追日》教学反思
2014/02/26 职场文书
槐乡的孩子教学反思
2014/04/27 职场文书
暑期培训班招生方案
2014/08/26 职场文书
党的群众路线教育实践活动对照检查材料(个人)
2014/09/24 职场文书
婚礼父母答谢词
2015/01/04 职场文书
2019年朋友圈经典励志语录50条
2019/07/05 职场文书
使用Python脚本对GiteePages进行一键部署的使用说明
2021/05/27 Python