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

关于缓冲查询和无缓冲查询
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//每次返回结果集的一条,即一个一维的数字数组.
(0)

相关推荐

  • mysql缓冲和缓存设置详解

    MySQL 可调节设置可以应用于整个 mysqld进程,也可以应用于单个客户机会话. 服务器端的设置 每个表都可以表示为磁盘上的一个文件,必须先打开,后读取.为了加快从文件中读取数据的过程,mysqld对这些打开文件进行了缓存,其最大数目由 /etc/mysqld.conf 中的table_cache 指定.清单 4给出了显示与打开表有关的活动的方式. 清单 4. 显示打开表的活动 mysql> SHOW STATUS LIKE 'open%tables'; +---------------+-

  • mysql的查询缓存说明

    对mysql查询缓存从五个角度进行详细的分析:Query Cache的工作原理.如何配置.如何维护.如何判断查询缓存的性能.适合的业务场景分析. 工作原理 查询缓存的工作原理,基本上可以概括为:缓存SELECT操作或预处理查询(注释:5.1.17开始支持)的结果集和SQL语句:新的SELECT语句或预处理查询语句,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写: 查询缓存对什么样的查询语句,无法缓存其记录集,大致有以下几类:查询语句中加了SQL_N

  • 使用Memcache缓存mysql数据库操作的原理和缓存过程浅析

    对于大型网站如facebook,ebay等网站,如果没有Memcache做为中间缓存层,数据访问不可能吃得消,对于一般网站,只要具备独立的服务器,完全可以通过配置Memcache提高网站访问速度和减少数据库压力,这里主要讨论一下Memcache和MySQL数据库交互过程的流程关系,了解Memcache的中间缓存层作用,从而深入了解Memcache机制原理. Memcache和MySQL交互流程图 如上图,传统的查询方法是直接查询数据库,数据库将结果返回给查询语句,而当有Memcache中间缓存层

  • 浅析MySQL内存的使用说明(全局缓存+线程缓存)

    首先我们来看一个公式,MySQL中内存分为全局内存和线程内存两大部分(其实并不全部,只是影响比较大的 部分): 复制代码 代码如下: per_thread_buffers=(read_buffer_size+read_rnd_buffer_size+sort_buffer_size+thread_stack+join_buffer_size+binlog_cache_size+tmp_table_size)*max_connectionsglobal_buffers=innodb_buffer_

  • MySQL缓存的查询和清除命令使用详解

    Mysql 查询缓存 查询缓存的作用就是当查询接收到一个和之前同样的查询,服务器将会从查询缓存种检索结果,而不是再次分析和执行上次的查询.这样就大大提高了性能,节省时间. 1.配置查询缓存 修改配置文件,修改[mysqld]下的query_cache_size和query_cache_type(如果没有则添加).其中query_cache_size表示缓存的大小,而query_cache_type有3个值,表示缓存那种类  型的select结果集,query_cache_type各个值如下: 0

  • 清空mysql 查询缓存的可行方法

    对一条sql进行优化时,发现原本很慢的一条sql(将近1分钟) 在第二次运行时, 瞬间就完成了(0.00sec) 这是因为mysql对同一条sql进行了缓存,服务器直接从上次的查询结果缓存中读取数据,而不是重新分析.执行sql. 可通过如下方法清空查询缓存 reset query cache;

  • MySQL高速缓存启动方法及参数详解(query_cache_size)

    MySQL query cache从4.1版本开始提供了,不过值今天本人才对其进行研究.默认配置下,MySQL的该功能是没有启动的,可能你通过show variables like '%query_cache%';会发现其变量have_query_cache的值是yes,MYSQL初学者很容易以为这个参数为YES就代表开启了查询缓存,实际上是不对的,该参数表示当前版本的MYSQL是否支持Query Cache,实际上是否开启查询缓存是看另外一个参数的值:query_cache_size ,该值为

  • mysql 设置查询缓存

    可将如下语句 query_cache_size = 268435456 query_cache_type = 1 query_cache_limit = 1048576 存放到/etc/my.cnf文件的[mysqld]下 然后重启mysql数据库 service mysqld restart 就会启动mysql的缓存机制Query Cache. 在使用中,查询缓存会存储一个 SELECT 查询的文本与被传送到客户端的相应结果. 如果之后接收到一个同样的查询,服务器将从查询缓存中检索结果,而不是

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

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

  • MySQL Innodb关键特性之插入缓冲(insert buffer)

    什么是insert buffer? 插入缓冲,也称之为insert buffer,它是innodb存储引擎的关键特性之一,我们经常会理解插入缓冲时缓冲池的一个部分,这样的理解是片面的,insert buffer的信息一部分在内存中,另外一部分像数据页一样,存在于物理页中. 在innodb中,我们知道,如果一个表有自增主键,那么对于这个表的默认插入是非常快的,注意,这里的主键是自增的,如果不是自增的,那么这个插入将会变成随机的,就可能带来数据页分裂的开销,这样,插入就不是顺序的,就会变慢.还有一种

  • MySQL数据库设计概念及多表查询和事物操作

    目录 数据库设计概念 数据库设计简介 表关系(多对多) 表关系(一对多) 表关系之一对一 多表查询 笛卡尔积现象 内连接查询 嵌套查询(子查询) 事务操作 事务的概念 手动提交事务 自动提交事务 事务原理和四大特征 事务原理 事务的四大特征 事务的并发访问引发的三个问题(面试) 事务的隔离级别 数据库设计概念 数据库设计简介 1.数据库设计概念 数据库设计就是根据业务系统具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型. 建立数据库中的表结构以及表与表之间的关联关系的过

  • Oracle、MySQL和SqlServe三种数据库分页查询语句的区别介绍

    先来定义分页语句将要用到的几个参数: int currentPage ; //当前页 int pageRecord ; //每页显示记录数 以之前的ADDRESSBOOK数据表为例(每页显示10条记录): 一.SqlServe下载 分页语句 String sql = "select top "+pageRecord +" * from addressbook where id not in (select top "+(currentPage-)*pageRecor

  • MySql带OR关键字的多条件查询语句

    上篇文章给大家介绍了Mysql带And关键字的多条件查询语句,下面给大家介绍MySql带OR关键字的多条件查询语句,感兴趣的朋友可以一起学习. MySQL带OR关键字的多条件查询,与AND关键字不同,OR关键字,只要记录满足任意一个条件,就会被查询出来. SELECT * | {字段名1,字段名2,--} FROM 表名 WHERE 条件表达式1 OR 条件表达式2 [-- OR 条件表达式n]; 查询student表中,id字段值小于15,或者gender字段值为nv的学生姓名 可以看出,返回

  • mysql explain的用法(使用explain优化查询语句)

    首先我来给一个简单的例子,然后再来解释explain列的信息. 表一:catefory 文章分类表: CREATE TABLE IF NOT EXISTS `category` ( `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=MyISAM INSERT INTO `test`.`category` VAL

  • MySQL中表子查询与关联子查询的基础学习教程

    MySQL 表子查询 表子查询是指子查询返回的结果集是 N 行 N 列的一个表数据. MySQL 表子查询实例 下面是用于例子的两张原始数据表: article 表: blog 表: SQL 如下: SELECT * FROM article WHERE (title,content,uid) IN (SELECT title,content,uid FROM blog) 查询返回结果如下所示: 该 SQL 的意义在于查找 article 表中指定的字段同时也存在于 blog 表中的所有的行(注

  • Mysql带And关键字的多条件查询语句

    MySQL带AND关键字的多条件查询,MySQL中,使用AND关键字,可以连接两个或者多个查询条件,只有满足所有条件的记录,才会被返回. SELECT * | {字段名1,字段名2,--} FROM 表名 WHERE 条件表达式1 AND 条件表达式2 [-- AND 条件表达式n]; 查询student表中,id字段值小于16,并且,gender字段值为nv的学生姓名 可以看出,查询条件必须都满足,才会返回 查询student表中,id字段值在12.13.14.15之中,name字段值以字符串

  • 详解MySql基本查询、连接查询、子查询、正则表达查询

    查询数据指从数据库中获取所需要的数据.查询数据是数据库操作中最常用,也是最重要的操作.用户可以根据自己对数据的需求,使用不同的查询方式.通过不同的查询方式,可以获得不同的数据.MySQL中是使用SELECT语句来查询数据的.在这一章中将讲解的内容包括. 1.查询语句的基本语法 2.在单表上查询数据 3.使用聚合函数查询数据 4.多表上联合查询 5.子查询 6.合并查询结果 7.为表和字段取别名 8.使用正则表达式查询 什么是查询? 怎么查的? 数据的准备如下: create table STUD

  • MySQL中列子查询与行子查询操作的学习教程

    MySQL 列子查询及 IN.ANY.SOME 和 ALL 操作符的使用 MySQL 列子查询 列子查询是指子查询返回的结果集是 N 行一列,该结果通常来自对表的某个字段查询返回. 一个列子查询的例子如下: SELECT * FROM article WHERE uid IN(SELECT uid FROM user WHERE status=1) 列子查询中使用 IN.ANY.SOME 和 ALL 操作符 由于列子查询返回的结果集是 N 行一列,因此不能直接使用 = > < >= &l

随机推荐