PHP查询MySQL大量数据的时候内存占用分析


Posted in PHP onJuly 22, 2011

昨天, 有同事在PHP讨论群里提到, 他做的一个项目由于MySQL查询返回的结果太多(达10万条), 从而导致PHP内存不够用. 所以, 他问, 在执行下面的代码遍历返回的MySQL结果之前, 数据是否已经在内存中了? -

while ($row = mysql_fetch_assoc($result)) { 

// ... 

}

当然, 这种问题有许多优化的方法. 不过, 就这个问题来讲, 我首先想到, MySQL是经典的C/S(Client/Server, 客户端/服务器)模型, 在遍历结果集之前, 底层的实现可能已经把所有的数据通过网络(假设使用TCP/IP)读到了Client的缓冲区, 也有另一种可能, 就是数据还在Server端的发送缓冲区里, 并没有传给Client.

在查看PHP和MySQL的源码之前, 我注意到PHP手册里有两个功能相近的函数:

mysql_query() 

mysql_unbuffered_query()

两个函数的字面意思和说明证实了我的想法, 前一个函数执行时, 会把所有的结果集从Server端读到Client端的缓冲区中, 而后一个则没有, 这就是”unbuffered(未缓冲)”的意思.

那就是说, 如果用mysql_unbuffered_query()执行了一条返回大量结果集的SQL语句, 在遍历结果之前, PHP的内存是没有被结果集占用的. 而用mysql_query()来执行同样的语句的话, 函数返回时, PHP的内存占用便会急剧增加, 立即耗光内存.

如果阅读PHP的相关代码, 可以看到这两个函数的实现上的异同:

/* {{{ proto resource mysql_query(string query [, int link_identifier]) 

Sends an SQL query to MySQL */ 

PHP_FUNCTION(mysql_query) 

{ 

php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_STORE_RESULT); 

} 

/* }}} */ 

/* {{{ proto resource mysql_unbuffered_query(string query [, int link_identifier]) 

Sends an SQL query to MySQL, without fetching and buffering the result rows */ 

PHP_FUNCTION(mysql_unbuffered_query) 

{ 

php_mysql_do_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQL_USE_RESULT); 

} 

/* }}} */

两个函数都调用了php_mysql_do_query(), 只差了第2个参数的不同, MYSQL_STORE_RESULT和MYSQL_USE_RESULT. 再看php_mysql_do_query()的实现:

if(use_store == MYSQL_USE_RESULT) { 

mysql_result=mysql_use_result(&mysql->conn); 

} else { 

mysql_result=mysql_store_result(&mysql->conn); 

}

mysql_use_result()和mysql_store_result()是MySQL的C API函数, 这两个C API函数的区别就是后者把结果集从MySQL Server端全部读取到了Client端, 前者只是读取了结果集的元信息.

回到PHP, 使用mysql_unbuffered_query(), 可以避免内存的立即占用. 如果在遍历的过程不对结果进行”PHP缓存”(如放到某数组中), 则整个执行过程虽然操作了十万条或者百万条或者更多的数据, 但PHP占用的内存始终是非常小的.

PHP 相关文章推荐
php adodb分页实现代码
Mar 19 PHP
《PHP编程最快明白》第七讲:php图片验证码与缩略图
Nov 01 PHP
Windows下利用Gvim写PHP产生中文乱码问题解决方法
Apr 20 PHP
php数组函数序列之end() - 移动数组内部指针到最后一个元素,并返回该元素的值
Oct 31 PHP
解析crontab php自动运行的方法
Jun 24 PHP
php增删改查示例自己写的demo
Sep 04 PHP
PHP生成不同颜色、不同大小的tag标签函数
Sep 23 PHP
php 伪静态之IIS篇
Jun 02 PHP
WordPress中查询文章的循环Loop结构及用法分析
Dec 17 PHP
thinkPHP中session()方法用法详解
Dec 08 PHP
mac os快速切换多个PHP版本的方法
Mar 07 PHP
PHP中引用类型和值类型功能与用法示例
Feb 26 PHP
PHP性能优化 产生高度优化代码
Jul 22 #PHP
PHP多个版本的分析解释
Jul 21 #PHP
QQ登录 PHP OAuth示例代码
Jul 20 #PHP
模板引擎正则表达式调试小技巧
Jul 20 #PHP
php中批量替换文件名的实现代码
Jul 20 #PHP
关于php连接mssql:pdo odbc sql server
Jul 20 #PHP
PHP mcrypt可逆加密算法分析
Jul 19 #PHP
You might like
PHP语法速查表
2007/01/02 PHP
在任意字符集下正常显示网页的方法一
2007/04/01 PHP
PHP XML error parsing SOAP payload on line 1
2010/06/17 PHP
php学习笔记 面向对象中[接口]与[多态性]的应用
2011/06/16 PHP
php数组函数序列之sort() 对数组的元素值进行升序排序
2011/11/02 PHP
教你php如何实现验证码
2016/01/20 PHP
laravel请求参数校验方法
2019/10/10 PHP
php+laravel依赖注入知识点总结
2019/11/04 PHP
jQuery 1.2.x 升? 1.3.x 注意事项
2009/05/06 Javascript
javascript 一些用法小结
2009/09/11 Javascript
jQuery对象初始化的传参方式
2015/02/26 Javascript
js实现精美的银灰色竖排折叠菜单
2015/05/16 Javascript
jquery+css3实现会动的小圆圈效果
2016/01/27 Javascript
基于javaScript的this指向总结
2017/07/22 Javascript
使用jquery+iframe做一个ajax上传效果(实例)
2017/08/24 jQuery
jQuery使用bind函数实现绑定多个事件的方法
2017/10/11 jQuery
使用vue + less 实现简单换肤功能的示例
2018/02/21 Javascript
浅谈vue引用静态资源需要注意的事项
2018/09/28 Javascript
纯JS实现五子棋游戏
2020/05/28 Javascript
通过实例解析json与jsonp原理及使用方法
2020/09/27 Javascript
[02:21]2018完美盛典章节片——初心
2018/12/17 DOTA
python中使用sys模板和logging模块获取行号和函数名的方法
2014/04/15 Python
Python中.py文件打包成exe可执行文件详解
2017/03/22 Python
python实现定时压缩指定文件夹发送邮件
2020/12/22 Python
Django错误:TypeError at / 'bool' object is not callable解决
2019/08/16 Python
Python获取二维数组的行列数的2种方法
2020/02/11 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
Python爬虫设置Cookie解决网站拦截并爬取蚂蚁短租的问题
2021/02/22 Python
业绩考核岗位职责
2014/02/01 职场文书
2014年大学学生会工作总结
2014/12/02 职场文书
周年庆典答谢词
2015/01/20 职场文书
导游词之介休绵山
2019/12/31 职场文书
Python如何利用正则表达式爬取网页信息及图片
2021/04/17 Python
再也不用花钱买漫画!Python爬取某漫画的脚本及源码
2021/06/09 Python
sqlserver连接错误之SQL评估期已过的问题解决
2022/03/23 SQL Server
SQL语句中EXISTS的详细用法大全
2022/06/25 MySQL