如何解决PHP里大量数据循环时内存耗尽的问题

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介:

最近在开发一个PHP程序时遇到了下面的错误:

 
 
  1. 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

 
  1. <?php 
  2. $mysqli  = new mysqli("localhost""my_user""my_password""world"); 
  3. $uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT); 
  4.  
  5. if ($uresult) { 
  6.    while ($row = $uresult->fetch_assoc()) { 
  7.        echo $row['Name'] . PHP_EOL; 
  8.    } 
  9. $uresult->close(); 
  10. ?> 

非缓冲查询方法二: pdo_mysql

 
  1. <?php 
  2. $pdo = new PDO("mysql:host=localhost;dbname=world"'my_user''my_pass'); 
  3. $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 
  4.  
  5. $uresult = $pdo->query("SELECT Name FROM City"); 
  6. if ($uresult) { 
  7.    while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) { 
  8.        echo $row['Name'] . PHP_EOL; 
  9.    } 
  10. ?> 

非缓冲查询方法三: mysql

 
  1. <?php 
  2. $conn = mysql_connect("localhost""my_user""my_pass"); 
  3. $db   = mysql_select_db("world"); 
  4.  
  5. $uresult = mysql_unbuffered_query("SELECT Name FROM City"); 
  6. if ($uresult) { 
  7.    while ($row = mysql_fetch_assoc($uresult)) { 
  8.        echo $row['Name'] . PHP_EOL; 
  9.    } 
  10. ?> 



来源:51CTO

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
14天前
|
存储
数据在内存中的存储之整数存储
数据在内存中的存储之整数存储
20 0
|
1天前
|
存储 编译器 程序员
C语言:数据在内存中的存储
C语言:数据在内存中的存储
8 2
|
10天前
|
缓存 PHP 数据库
【PHP开发专栏】PHP代码优化与内存管理
【4月更文挑战第30天】本文探讨了PHP的代码优化和内存管理,旨在提升Web应用性能。第一部分介绍了代码优化,包括减少代码重复、选择高效数据结构、减少函数调用、使用缓存、优化数据库查询、图像处理和正则表达式优化。第二部分讲解内存管理,建议减少全局变量、正确使用内存分配函数、利用对象引用计数、避免内存泄露及优化内存分配。第三部分通过在线论坛的缓存应用和图像处理的内存池技术展示了实践案例。
|
15天前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
|
21天前
|
存储 缓存 算法
php遇到内存溢出
php遇到内存溢出
15 3
|
21天前
|
存储 NoSQL Oracle
Oracle 12c的内存列存储:数据的“闪电侠”
【4月更文挑战第19天】Oracle 12c的内存列存储以超高速度革新数据处理,结合列存储与内存技术,实现快速查询与压缩。它支持向量化查询和并行处理,提升效率,但需合理配置以平衡系统资源。作为数据管理员,应善用此功能,适应业务需求和技术发展。
|
1月前
|
存储 C语言
数据在内存中的存储2
数据在内存中的存储2
|
1月前
|
存储 编译器
数据在内存中的存储1
数据在内存中的存储
|
2月前
|
存储 编译器 程序员
【C语言】整形数据和浮点型数据在内存中的存储
【C语言】整形数据和浮点型数据在内存中的存储
17 0
|
2月前
|
存储 缓存 物联网
MQTT常见问题之MQTT发送消息过多内存不够处理不过来如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总: