对比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实现的仿阿里巴巴实现同类产品翻页
Dec 11 PHP
ThinkPHP快速入门实例教程之数据分页
Jul 01 PHP
Windows下的PHP 5.3.x安装 Zend Guard Loader教程
Sep 06 PHP
php实现的css文件背景图片下载器代码
Nov 11 PHP
PHP+swoole实现简单多人在线聊天群发
Jan 19 PHP
php compact 通过变量创建数组
Nov 15 PHP
PHP文件操作详解
Dec 30 PHP
PHP实现验证码校验功能
Nov 16 PHP
tp5(thinkPHP5)操作mongoDB数据库的方法
Jan 20 PHP
PHP使用mongoclient简单操作mongodb数据库示例
Feb 08 PHP
php实现银联商务公众号+服务窗支付的示例代码
Oct 12 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
PHP Memcached + APC + 文件缓存封装实现代码
2010/03/11 PHP
详解thinkphp中的volist标签
2018/01/15 PHP
在Laravel中实现使用AJAX动态刷新部分页面
2019/10/15 PHP
js 实现复制到粘贴板的功能代码
2010/05/13 Javascript
通过Javascript创建一个选择文件的对话框代码
2012/06/16 Javascript
关于js中alert弹出窗口文本换行问题简单详细说明
2012/12/11 Javascript
JS实现div内部的文字或图片自动循环滚动代码
2013/04/19 Javascript
js 控制页面跳转的5种方法
2013/09/09 Javascript
浅谈javascript事件取消和阻止冒泡
2015/05/26 Javascript
js实现鼠标点击左上角滑动菜单效果代码
2015/09/06 Javascript
JavaScript常用字符串与数组扩展函数小结
2016/04/24 Javascript
限制文本框只能输入数字||只能是数字和小数点||只能是整数和浮点数
2016/05/27 Javascript
jquery设置表单元素为不可用的简单代码
2016/07/04 Javascript
JS实现数字格式千分位相互转换方法
2016/08/01 Javascript
jQuery EasyUI 右键菜单--关闭标签/选项卡的简单实例
2016/10/10 Javascript
js案例之鼠标跟随jquery版(实例讲解)
2017/07/21 jQuery
JS分页的实现(同步与异步)
2017/09/16 Javascript
React Native预设占位placeholder的使用
2017/09/28 Javascript
NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法
2018/10/17 NodeJs
详解jQuery-each()方法
2019/03/13 jQuery
jQuery实现动态添加和删除input框代码实例
2019/03/29 jQuery
VueJs里利用CryptoJs实现加密及解密的方法示例
2019/04/29 Javascript
原生JS实现贪吃蛇小游戏
2020/03/09 Javascript
js制作提示框插件
2020/12/24 Javascript
python实现画一颗树和一片森林
2018/06/25 Python
python 使用值来排序一个字典的方法
2018/11/16 Python
如何利用Python模拟GitHub登录详解
2019/07/15 Python
使用python批量转换文件编码为UTF-8的实现
2020/04/03 Python
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
澳大利亚排名第一的露营和户外设备在线零售商:Outbax
2020/05/06 全球购物
J2EE面试题大全
2016/08/06 面试题
高一家长会邀请函
2014/01/12 职场文书
书法大赛策划方案
2014/06/04 职场文书
工程索赔意向书
2014/08/30 职场文书
JavaCV实现照片马赛克效果
2022/01/22 Java/Android
yolov5返回坐标的方法实例
2022/03/17 Python