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中的超全局变量
Oct 09 PHP
资料注册后发信小技巧
Oct 09 PHP
destoon调用自定义模板及样式的公告栏
Jun 21 PHP
PHP操作FTP类 (上传、下载、移动、创建等)
Mar 31 PHP
Yii实现显示静态页的方法
Apr 25 PHP
实例讲解YII2中多表关联的使用方法
Jul 21 PHP
利用laravel搭建一个迷你博客实战教程
Aug 13 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
Jun 14 PHP
PHP封装的page分页类定义与用法完整示例
Dec 24 PHP
PHP使用mongoclient简单操作mongodb数据库示例
Feb 08 PHP
Laravel如何创建服务器提供者实例代码
Apr 15 PHP
Yii框架分页技术实例分析
Aug 30 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 日志缩略名的创建函数代码
2010/05/26 PHP
php获得网站访问统计信息类Compete API用法实例
2015/04/02 PHP
PHP addcslashes()函数讲解
2019/02/03 PHP
Laravel框架中集成MongoDB和使用详解
2019/10/17 PHP
javascript 数组学习资料收集
2010/04/11 Javascript
javascript 隔行换色函数代码
2010/10/24 Javascript
JS 日期比较大小的简单实例
2014/01/13 Javascript
js实现基于正则表达式的轻量提示插件
2015/08/29 Javascript
JS中的==运算: [''] == false —>true
2016/07/24 Javascript
Angularjs 设置全局变量的方法总结
2016/10/20 Javascript
Nodejs下DNS缓存问题浅析
2016/11/16 NodeJs
JS实现的相册图片左右滚动完整实例
2016/11/23 Javascript
jQuery实现背景滑动菜单
2016/12/02 Javascript
JavaScript实现简单的树形菜单效果
2017/06/23 Javascript
react中实现搜索结果中关键词高亮显示
2018/07/31 Javascript
JavaScript折半查找(二分查找)算法原理与实现方法示例
2018/08/06 Javascript
HTML+JavaScript实现扫雷小游戏
2019/09/30 Javascript
快速了解Vue父子组件传值以及父调子方法、子调父方法
2020/07/15 Javascript
JS前后端实现身份证号验证代码解析
2020/07/23 Javascript
vue监听滚动事件的方法
2020/12/21 Vue.js
Python 元类使用说明
2009/12/18 Python
Python 20行简单实现有道在线翻译的详解
2019/05/15 Python
python读取并写入mat文件的方法
2019/07/12 Python
django框架使用方法详解
2019/07/18 Python
解决安装python3.7.4报错Can''t connect to HTTPS URL because the SSL module is not available
2019/07/31 Python
详解Anconda环境下载python包的教程(图形界面+命令行+pycharm安装)
2019/11/11 Python
python利用datetime模块计算程序运行时间问题
2020/02/20 Python
详解Python设计模式之策略模式
2020/06/15 Python
推荐值得学习的12款python-web开发框架
2020/08/10 Python
Python析构函数__del__定义原理解析
2020/11/20 Python
[原创]赚疯了!转手立赚800+?大佬的python「抢茅台脚本」使用教程
2021/01/12 Python
HTML5安全介绍之内容安全策略(CSP)简介
2012/07/10 HTML / CSS
母亲80寿诞答谢词
2014/01/16 职场文书
2014年党员教师自我剖析材料
2014/09/30 职场文书
2015年社区党建工作汇报材料
2015/06/25 职场文书
Java 中的 Unsafe 魔法类的作用大全
2021/06/26 Java/Android