文档章节

PHP+MySQL缓冲查询和无缓冲查询

eechen
 eechen
发布于 2015/12/30 10:46
字数 927
阅读 1204
收藏 3
http://php.net/manual/zh/mysqlinfo.concepts.buffering.php
http://php.net/manual/zh/mysqli.query.php
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();

http://php.net/manual/zh/mysqli-stmt.fetch.php
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);

http://php.net/mysqli
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   每次返回结果集的一条,即一个一维的数字数组.

© 著作权归作者所有

共有 人打赏支持
eechen

eechen

粉丝 980
博文 107
码字总数 55962
作品 1
深圳
加载中

评论(1)

MySQL 优化之 query_cache_limit

querycachelimit querycachelimit指定单个查询能够使用的缓冲区大小,缺省为1M。 优化querycachesize 从4.0.1开始,MySQL提供了查询缓冲机制。使用查询缓冲,MySQL将SELECT语句和查询结果存放...

鉴客
2011/08/16
3.5K
0
mysql 优化(1)

一、 通过查询缓冲提高查询速度   一般我们使用SQL语句进行查询时,数据库服务器每次在收到客户端 发来SQL后,都会执行这条SQL语句。但当在一定间隔内(如1分钟内),接到完全一样的SQL语句...

真爱2015
2015/12/07
109
1
如何解决PHP里大量数据循环时内存耗尽的问题

在开发一个PHP程序时我们有时会遇到了下面的错误: 代码如下:PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted 错误信息显示允许的最大内存已经耗尽。遇到这样的错误起...

snowing1990
2016/03/07
19
0
PHP大量数据循环时内存耗尽问题的解决方案

最近在开发一个PHP程序时遇到了下面的错误: PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted 错误信息显示允许的最大内存已经耗尽。遇到这样的错误起初让我很诧异,但...

snowing1990
2016/04/15
12
0
你知道这样可以解决PHP里大量数据循环时内存耗尽的问题吗?

最近在开发一个PHP程序时遇到了下面的错误: PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted 错误信息显示允许的最大内存已经耗尽。遇到这样的错误起初让我很诧异,但...

咦我的天
2017/07/17
178
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Go语言_通神之路(2)

1、包 每个Go程序都是由包构成,从main包开始运行,就是我上一篇讲到的,都是从main函数开始执行,但是必须在main包下面! package mainimport ( "fmt" "math/rand")func ...

木九天
昨天
4
0
51.php-fpm的pool 慢日志 open_basedir 进程管理

12.21 php-fpm的pool 12.22 php-fpm慢执行日志(测试时报错) 12.23 open_basedir 12.24 php-fpm进程管理 12.21 php-fpm的pool: php-fpm里的pool也叫池子,咱们之前加入过www的配置,这个w...

王鑫linux
昨天
0
0
java内存模型概述

1、Java虚拟机运行时数据分区图 程序计数器:线程私有,是一块较小的内存空间,它是当前线程所执行的字节码文件的行号指示器 java虚拟机栈:线程私有,其生命周期与线程相同,这也就是我们平...

京一
昨天
1
0
shell学习之test语法

因为if-then语句不能测试退出状态码之外的条件,所以提供了test, 如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0;如果条件不成立,test命令就会退出并返回非零的退出状态...

woshixin
昨天
0
0
openJDK之如何下载各个版本的openJDK源码

如果我们需要阅读openJDK的源码,那么需要下载,那么该去哪下载呢? 现在JDK已经发展到版本10了,11已经处于计划中,如果需要特定版本的openJDK,它们的下载链接在哪呢? 1.openJDK的项目 链接...

汉斯-冯-拉特
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部