对比PHP对MySQL的缓冲查询和无缓冲查询


Posted in PHP onJuly 01, 2016

关于缓冲查询和无缓冲查询
MySQL的客户端有两种类型的查询:
缓冲查询:将接收查询的结果并把他们存储在客户端的缓存中,而且接下来获取行记录的请求仅仅从本地内获取。
(1)优点:可以在结果集中自由地移动“当前行”的指针,这样很容易找到,因为结果是存在客户端的。
(2)缺点:需要额外的内存来存储这些结果集,而且需要大量的内存,另外,php中用来运行查询的函数会一直到所有的结果都接收才会返回值。

无缓冲查询:会限制你通过严格的顺序访问查询结果。但他不需要额外的内存来存储整个结果集。你可以在MySQL服务器开始返回值的时候就开始获取而处理或显示数据行。当使用无缓冲结果集时,必须使用mysql_fetch_row函数获取所以的数据行,或者在给服务器发送其他任何命令前用mysql_free_result函数关闭结果集。

哪种类型的查询好?最好的根据是具体情况而定,无缓冲查询在结果集巨大的时为你节省大量的临时内存,而且查询不需要排序时,php在MySQL数据库实际上还在处理时就可以获得第一个数据行。
缓存查询便于寻找,它可以提供一个全面的寻找加速。因为每一个单独的查询的都会快读结束,mysql快速的获取结果集并存放在内存中,而不是在处理PHP代码时保持查询为可用的。
另外一个无缓冲查询的限制是在所有的数据行都被读取或者结果集用mysqli_free_result释放之前,你将无法向服务器发送任何命令。

PHP+MySQL缓冲查询和无缓冲查询
PHP MySQL查询(mysqli,pdo_mysql)默认使用缓冲模式.
也就是说查询结果将一次性从MySQL传输到PHP进程内存中,
这时可以统计结果集的行数,以及移动结果集指针.
缓冲模式下,如果结果集很大,那么PHP进程也会占用大量的内存,
直到结果集被unset或者free.

store_result用于缓冲模式,所有结果一次性存储到PHP进程中:

mysqli::query MYSQLI_STORE_RESULT 
mysqli::store_result 
mysqli_stmt::store_result

如果PHP的MySQL数据库驱动底层用的是libmysqlclient,那么memory_limit不能统计到结果集占用的内存,
除非结果集已经赋值给PHP变量,如果底层使用mysqlnd作为驱动时则可以统计到(PHP从5.4开始底层默认使用mysqlnd).
无缓冲模式下执行的查询将会返回一个resource资源引用,位于MySQL的查询结果等待PHP获取.
无缓冲模式下,PHP进程占用的内存很少,但会增大MySQL服务器的负载.
在PHP取回所有结果前,在当前数据库连接下不能发送其他的查询请求.

use_result表示无缓冲查询:

mysqli::query MYSQLI_USE_RESULT 
mysqli::use_result

总结:
当结果集不大时,或者需要在读取所有行前获取结果集行数时,使用缓冲查询(默认).
当结果集很大时,使用无缓冲查询,避免PHP进程占用大量的内存.

$rs = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT); 
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); 
$rs = $pdo->query("SELECT * FROM City");

默认情况下,mysqli_stmt的SELECT查询结果将留在MySQL服务器上,等待fetch方法把记录逐条取回到PHP程序中,这样做会降低性能,但能节省内存.
如果需要对所有记录进行处理,可以调用mysqli_stmt::store_result,把所有结果一次性全部传回到PHP程序中,
这样做更高效,能减轻MySQL服务器的负担,虽然内存占用会多一些.
如果获取SELECT语句查找到了多少条记录,可以用 mysqli_stmt::$num_rows 获取.
这个属性只有在提前执行过 mysqli_stmt::store_result 方法,将全部查询结果传回到PHP程序中的情况下才可以使用.
对比 mysqli_result::$num_rows 则不没有这个限制.
用 mysqli_stmt::free_result 关闭 mysqli_stmt::store_result:

$stmt->store_result(); 
echo $stmt->num_rows; 
$stmt->free_result();
mysqli_stmt::store_result能让mysqli_stmt::fetch更高效,但也需要用mysqli_stmt::free_result显式关闭. 

可以用mysqli_stmt::get_result拿到结果集对象$result,然后mysqli_result::fetch_all拿到查询数组$results:
$result = $stmt->get_result(); 
$results = $result->fetch_all(MYSQLI_ASSOC);
整理一下相关参数:
mysqli::query//执行SQL,成功返回mysqli_result(SELECT,SHOW,DESCRIBE操作)对象或TRUE(其他操作),失败返回FALSE.用mysqli::close关闭.
mysqli::prepare//预处理SQL,成功返回statement对象,失败返回FALSE.
mysqli_stmt::execute//执行SQL.用mysqli_stmt::close关闭.
mysqli_stmt::store_result//取回全部查询结果(SELECT,SHOW,DESCRIBE,EXPLAIN)到PHP,可选.用mysqli_stmt::free_result关闭.
mysqli_stmt::bind_result//把prepare和execute产生的结构绑定结果到变量,然后在mysqli_stmt::fetch中把这些变量输出或赋值.
mysqli_stmt::fetch//每次返回结果集的一条,赋值给mysqli_stmt::bind_result绑定的变量.
mysqli_stmt::get_result//获得结果对象,然后调用mysqli_result::fetch_all就能返回结果集数组.mysqlnd下可用.
mysqli_result::fetch_all//返回一个结果集数组(MYSQLI_NUM(默认),MYSQLI_ASSOC,MYSQLI_BOTH),用mysqli_result::close关闭.mysqlnd下可用.
mysqli_result::fetch_array//每次返回结果集的一条,包含一个一维的数字数组和关联数组.
mysqli_result::fetch_assoc//每次返回结果集的一条,即一个一维的关联数组.
mysqli_result::fetch_row//每次返回结果集的一条,即一个一维的数字数组.
PHP 相关文章推荐
配置最新的PHP加MYSQL服务器
Oct 09 PHP
php 获取完整url地址
Dec 20 PHP
PHP 程序授权验证开发思路
Jul 09 PHP
php后台多用户权限组思路与实现程序代码分享
Feb 13 PHP
php版微信公众号接口实现发红包的方法
Oct 14 PHP
PHP数组操作简单案例分析
Oct 15 PHP
PHP生成图片缩略图类示例
Jan 12 PHP
php实现的XML操作(读取)封装类完整实例
Feb 23 PHP
php实现统计二进制中1的个数算法示例
Jan 23 PHP
PHP实现函数内修改外部变量值的方法示例
Dec 28 PHP
PHP获取HTTP body内容的方法
Dec 31 PHP
php多进程并发编程防止出现僵尸进程的方法分析
Feb 28 PHP
PHP处理CSV表格文件的常用操作方法总结
Jul 01 #PHP
PHP读书笔记整理_结构语句详解
Jul 01 #PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
Jul 01 #PHP
php投票系统之增加与删除投票(管理员篇)
Jul 01 #PHP
PHP读书笔记_运算符详解
Jul 01 #PHP
php+MySql实现登录系统与输出浏览者信息功能
Jul 01 #PHP
php无法连接mysql数据库的正确解决方法
Jul 01 #PHP
You might like
解决文件名解压后乱码的问题 将文件名进行转码的代码
2012/01/10 PHP
Apache服务器下防止图片盗链的办法
2015/07/06 PHP
PHP的PDO连接讲解
2019/01/24 PHP
获取Javscript执行函数名称的方法
2006/12/22 Javascript
JavaScript splice()方法详解
2020/09/22 Javascript
jquery和ajax的关系详细介绍
2013/11/29 Javascript
自己动手写的javascript前端等待控件
2015/10/30 Javascript
表单验证正则表达式实例代码详解
2015/11/09 Javascript
Web前端新人笔记之jquery入门心得(新手必看)
2016/05/17 Javascript
微信小程序访问node.js接口服务器搭建教程
2017/04/25 Javascript
使用Bootstrap4 + Vue2实现分页查询的示例代码
2017/12/21 Javascript
微信小程序实现列表下拉刷新上拉加载
2020/07/29 Javascript
说说Vue.js中的functional函数化组件的使用
2019/02/12 Javascript
快速对接payjq的个人微信支付接口过程解析
2019/08/15 Javascript
JavaScript 斐波那契数列 倒序输出 输出100以内的质数代码实例
2019/09/11 Javascript
Layui tree 下拉菜单树的实例代码
2019/09/21 Javascript
vue 导航内容设置选中状态样式的例子
2019/11/01 Javascript
Nodejs使用archiver-zip-encrypted库加密压缩文件时报错(解决方案)
2019/11/18 NodeJs
vue之封装多个组件调用同一接口的案例
2020/08/11 Javascript
[03:42]2014DOTA2国际邀请赛 第三日比赛排位扑朔迷离
2014/07/12 DOTA
django2用iframe标签完成网页内嵌播放b站视频功能
2018/06/20 Python
详解Python 数据库的Connection、Cursor两大对象
2018/06/25 Python
Python控制键盘鼠标pynput的详细用法
2019/01/28 Python
Python paramiko模块使用解析(实现ssh)
2019/08/30 Python
简单了解django文件下载方式
2020/02/10 Python
python GUI框架pyqt5 对图片进行流式布局的方法(瀑布流flowlayout)
2020/03/12 Python
Python Pygame实现俄罗斯方块
2021/02/19 Python
经济实惠的名牌太阳镜和眼镜:Privé Revaux
2021/02/07 全球购物
结婚典礼证婚词
2014/01/08 职场文书
两只小狮子教学反思
2014/02/05 职场文书
《北京的春节》教学反思
2014/04/07 职场文书
2014初中数学教研组工作总结
2014/12/19 职场文书
罚站检讨书
2015/01/29 职场文书
2015年小学生国庆节演讲稿
2015/07/30 职场文书
医务人员医德医风心得体会
2016/01/25 职场文书
导游词创作书写原则以及开场白技巧怎么学?
2019/09/25 职场文书