一个大佬最近在开发一个PHP程序时遇到了下面的错误:
PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted
错误信息显示允许的最大内存已经耗尽。这个大佬将正在开发的程序用一个foreach循环语句在一个有4万条记录的表里全表搜索具有特定特征的数据,也就是说,一次要把4万条数据取出,然后逐条检查每天数据。可想而知,4万条数据全部加载到内存中,内存不爆才怪。
PHP里提供有非一次全部加载数据的API,是像处理流媒体那样,随用随取随丢、数据并不会积累在内存的查询方法。
api:Application Programming Interface,应用程序编程接口,是一些预先定义的函数
PHP的查询缺省模式是缓冲模式,即查询数据结果会一次全部提取到内存里供PHP程序处理。这样给了PHP程序额外的功能,比如说,计算行数,将指针指向某一行等。更重要的是程序可以对数据集反复进行二次查询和过滤等操作。但这种缓冲查询模式的缺陷就是消耗内存,也就是用空间换速度。
相对的,另外一种PHP查询模式是非缓冲查询,数据库服务器会一条一条的返回数据,而不是一次全部返回,这样的结果就是PHP程序消耗较少的内存,但却增加了数据库服务器的压力,因为数据库会一直等待PHP来取数据,一直到数据全部取完。
缓冲查询模式适用于小数据量查询,而非缓冲查询适应于大数据量查询。
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.
当结果集很大时,使用无缓冲查询,避免PHP进程占用大量的内存.
在PHP中“::”这个叫范围解析操作符,又名域运算符
“::”符号可以认为是与C语言中的“.”相似的,而它更像C++中(Perl)的::类范围操作符。
php调用类的内部静态成员,或者是类之间调用就要用::
mysql_fetch_row() 函数从结果集中取得一行作为数字数组。
在PHP里面 ->用来引用对象的成员,包括属性和方法,=>只用来数组赋值。
PHP中可以用PHP_EOL来替代,以提高代码的源代码级可移植性
<?php
echo PHP_EOL;
//windows平台相当于 echo "\r\n";
//unix\linux平台相当于 echo "\n";
//mac平台相当于 echo "\r";
换行符
unix系列用 \n
windows系列用 \r\n
mac用 \r
参考:
http://www.webhek.com/post/php-buffered-and-unbuffered-queries.html
https://www.jb51.net/article/87776.htm