对比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的面试题集,附我的答案和分析(一)
Nov 19 PHP
php下intval()和(int)转换使用与区别
Jul 18 PHP
PHP 类型转换函数intval
Jun 20 PHP
用PHP查询搜索引擎排名位置的代码
Jan 05 PHP
PHP获取和操作配置文件php.ini的几个函数介绍
Jun 24 PHP
解析linux下安装memcacheq(mcq)全过程笔记
Jun 27 PHP
php var_export与var_dump 输出的不同
Aug 09 PHP
jQuery Mobile + PHP实现文件上传
Dec 12 PHP
PHP获取音频文件的相关信息
Jun 22 PHP
php 获取xml接口数据的处理方法
May 31 PHP
Yii支持多域名cors原理的实现
Dec 05 PHP
TP5框架实现的数据库备份功能示例
Apr 05 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 xfocus防注入资料
2008/04/27 PHP
set_include_path和get_include_path使用及注意事项
2013/02/02 PHP
解析dedeCMS验证码的实现代码
2013/06/07 PHP
微信小程序 消息推送php服务器验证实例详解
2017/03/30 PHP
读jQuery之十二 删除事件核心方法
2011/07/31 Javascript
图片延迟加载的实现代码(模仿懒惰)
2013/03/29 Javascript
hover的用法及live的用法介绍(鼠标悬停效果)
2013/03/29 Javascript
Javascript中判断变量是数组还是对象(array还是object)
2013/08/14 Javascript
JavaScript Promise启示录
2014/08/12 Javascript
jQuery简单tab切换效果实现方法
2015/04/08 Javascript
jQuery实现带遮罩层效果的blockUI弹出层示例【附demo源码下载】
2016/09/14 Javascript
canvas实现十二星座星空图
2017/02/14 Javascript
jQuery手风琴的简单制作
2017/05/12 jQuery
详解layui中的树形关于取值传值问题
2018/01/16 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
[01:10]DOTA2亚洲邀请赛 征战号角响彻全场
2015/01/06 DOTA
Python实现九宫格式的朋友圈功能内附“马云”朋友圈
2019/05/07 Python
django框架面向对象ORM模型继承用法实例分析
2019/07/29 Python
Python socket非阻塞模块应用示例
2019/09/12 Python
python框架django项目部署相关知识详解
2019/11/04 Python
python+tifffile之tiff文件读写方式
2020/01/13 Python
python 实现IP子网计算
2021/02/18 Python
HTML5的结构和语义(1):前言
2008/10/17 HTML / CSS
XML文档面试题
2015/08/05 面试题
.NET常见笔试题集
2012/12/01 面试题
国际商务专业学生个人的自我评价
2013/09/28 职场文书
学生生病请假条范文
2014/02/16 职场文书
程序员求职信
2014/04/16 职场文书
招股说明书范本
2014/05/06 职场文书
市级绿色学校申报材料
2014/08/25 职场文书
2015医德医风个人工作总结
2015/04/02 职场文书
党支部创先争优公开承诺书
2015/04/30 职场文书
关于做家务的心得体会
2016/01/23 职场文书
详解JavaScript中Arguments对象用途
2021/08/30 Javascript
《进击的巨人》新联动CM 兵长强势出击兽巨人
2022/04/05 日漫
win11自动弹出虚拟键盘怎么关闭? Win11关闭虚拟键盘的技巧
2023/01/09 数码科技