對(duì)比PHP對(duì)MySQL的緩沖查詢和無緩沖查詢
關(guān)于緩沖查詢和無緩沖查詢
MySQL的客戶端有兩種類型的查詢:
緩沖查詢:將接收查詢的結(jié)果并把他們存儲(chǔ)在客戶端的緩存中,而且接下來獲取行記錄的請(qǐng)求僅僅從本地內(nèi)獲取。
(1)優(yōu)點(diǎn):可以在結(jié)果集中自由地移動(dòng)“當(dāng)前行”的指針,這樣很容易找到,因?yàn)榻Y(jié)果是存在客戶端的。
(2)缺點(diǎn):需要額外的內(nèi)存來存儲(chǔ)這些結(jié)果集,而且需要大量的內(nèi)存,另外,php中用來運(yùn)行查詢的函數(shù)會(huì)一直到所有的結(jié)果都接收才會(huì)返回值。
無緩沖查詢:會(huì)限制你通過嚴(yán)格的順序訪問查詢結(jié)果。但他不需要額外的內(nèi)存來存儲(chǔ)整個(gè)結(jié)果集。你可以在MySQL服務(wù)器開始返回值的時(shí)候就開始獲取而處理或顯示數(shù)據(jù)行。當(dāng)使用無緩沖結(jié)果集時(shí),必須使用mysql_fetch_row函數(shù)獲取所以的數(shù)據(jù)行,或者在給服務(wù)器發(fā)送其他任何命令前用mysql_free_result函數(shù)關(guān)閉結(jié)果集。
哪種類型的查詢好?最好的根據(jù)是具體情況而定,無緩沖查詢在結(jié)果集巨大的時(shí)為你節(jié)省大量的臨時(shí)內(nèi)存,而且查詢不需要排序時(shí),php在MySQL數(shù)據(jù)庫實(shí)際上還在處理時(shí)就可以獲得第一個(gè)數(shù)據(jù)行。
緩存查詢便于尋找,它可以提供一個(gè)全面的尋找加速。因?yàn)槊恳粋€(gè)單獨(dú)的查詢的都會(huì)快讀結(jié)束,mysql快速的獲取結(jié)果集并存放在內(nèi)存中,而不是在處理PHP代碼時(shí)保持查詢?yōu)榭捎玫摹?br />
另外一個(gè)無緩沖查詢的限制是在所有的數(shù)據(jù)行都被讀取或者結(jié)果集用mysqli_free_result釋放之前,你將無法向服務(wù)器發(fā)送任何命令。
PHP+MySQL緩沖查詢和無緩沖查詢
PHP MySQL查詢(mysqli,pdo_mysql)默認(rèn)使用緩沖模式.
也就是說查詢結(jié)果將一次性從MySQL傳輸?shù)絇HP進(jìn)程內(nèi)存中,
這時(shí)可以統(tǒng)計(jì)結(jié)果集的行數(shù),以及移動(dòng)結(jié)果集指針.
緩沖模式下,如果結(jié)果集很大,那么PHP進(jìn)程也會(huì)占用大量的內(nèi)存,
直到結(jié)果集被unset或者free.
store_result用于緩沖模式,所有結(jié)果一次性存儲(chǔ)到PHP進(jìn)程中:
mysqli::query MYSQLI_STORE_RESULT mysqli::store_result mysqli_stmt::store_result
如果PHP的MySQL數(shù)據(jù)庫驅(qū)動(dòng)底層用的是libmysqlclient,那么memory_limit不能統(tǒng)計(jì)到結(jié)果集占用的內(nèi)存,
除非結(jié)果集已經(jīng)賦值給PHP變量,如果底層使用mysqlnd作為驅(qū)動(dòng)時(shí)則可以統(tǒng)計(jì)到(PHP從5.4開始底層默認(rèn)使用mysqlnd).
無緩沖模式下執(zhí)行的查詢將會(huì)返回一個(gè)resource資源引用,位于MySQL的查詢結(jié)果等待PHP獲取.
無緩沖模式下,PHP進(jìn)程占用的內(nèi)存很少,但會(huì)增大MySQL服務(wù)器的負(fù)載.
在PHP取回所有結(jié)果前,在當(dāng)前數(shù)據(jù)庫連接下不能發(fā)送其他的查詢請(qǐng)求.
use_result表示無緩沖查詢:
mysqli::query MYSQLI_USE_RESULT mysqli::use_result
總結(jié):
當(dāng)結(jié)果集不大時(shí),或者需要在讀取所有行前獲取結(jié)果集行數(shù)時(shí),使用緩沖查詢(默認(rèn)).
當(dāng)結(jié)果集很大時(shí),使用無緩沖查詢,避免PHP進(jìn)程占用大量的內(nèi)存.
$rs = $mysqli->query("SELECT * FROM City", MYSQLI_USE_RESULT); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $rs = $pdo->query("SELECT * FROM City");
默認(rèn)情況下,mysqli_stmt的SELECT查詢結(jié)果將留在MySQL服務(wù)器上,等待fetch方法把記錄逐條取回到PHP程序中,這樣做會(huì)降低性能,但能節(jié)省內(nèi)存.
如果需要對(duì)所有記錄進(jìn)行處理,可以調(diào)用mysqli_stmt::store_result,把所有結(jié)果一次性全部傳回到PHP程序中,
這樣做更高效,能減輕MySQL服務(wù)器的負(fù)擔(dān),雖然內(nèi)存占用會(huì)多一些.
如果獲取SELECT語句查找到了多少條記錄,可以用 mysqli_stmt::$num_rows 獲取.
這個(gè)屬性只有在提前執(zhí)行過 mysqli_stmt::store_result 方法,將全部查詢結(jié)果傳回到PHP程序中的情況下才可以使用.
對(duì)比 mysqli_result::$num_rows 則不沒有這個(gè)限制.
用 mysqli_stmt::free_result 關(guān)閉 mysqli_stmt::store_result:
$stmt->store_result(); echo $stmt->num_rows; $stmt->free_result();
可以用mysqli_stmt::get_result拿到結(jié)果集對(duì)象$result,然后mysqli_result::fetch_all拿到查詢數(shù)組$results:
$result = $stmt->get_result(); $results = $result->fetch_all(MYSQLI_ASSOC);
mysqli::query//執(zhí)行SQL,成功返回mysqli_result(SELECT,SHOW,DESCRIBE操作)對(duì)象或TRUE(其他操作),失敗返回FALSE.用mysqli::close關(guān)閉. mysqli::prepare//預(yù)處理SQL,成功返回statement對(duì)象,失敗返回FALSE. mysqli_stmt::execute//執(zhí)行SQL.用mysqli_stmt::close關(guān)閉. mysqli_stmt::store_result//取回全部查詢結(jié)果(SELECT,SHOW,DESCRIBE,EXPLAIN)到PHP,可選.用mysqli_stmt::free_result關(guān)閉. mysqli_stmt::bind_result//把prepare和execute產(chǎn)生的結(jié)構(gòu)綁定結(jié)果到變量,然后在mysqli_stmt::fetch中把這些變量輸出或賦值. mysqli_stmt::fetch//每次返回結(jié)果集的一條,賦值給mysqli_stmt::bind_result綁定的變量. mysqli_stmt::get_result//獲得結(jié)果對(duì)象,然后調(diào)用mysqli_result::fetch_all就能返回結(jié)果集數(shù)組.mysqlnd下可用. mysqli_result::fetch_all//返回一個(gè)結(jié)果集數(shù)組(MYSQLI_NUM(默認(rèn)),MYSQLI_ASSOC,MYSQLI_BOTH),用mysqli_result::close關(guān)閉.mysqlnd下可用. mysqli_result::fetch_array//每次返回結(jié)果集的一條,包含一個(gè)一維的數(shù)字?jǐn)?shù)組和關(guān)聯(lián)數(shù)組. mysqli_result::fetch_assoc//每次返回結(jié)果集的一條,即一個(gè)一維的關(guān)聯(lián)數(shù)組. mysqli_result::fetch_row//每次返回結(jié)果集的一條,即一個(gè)一維的數(shù)字?jǐn)?shù)組.
相關(guān)文章
php數(shù)組函數(shù)序列之a(chǎn)rray_keys() - 獲取數(shù)組鍵名
array_keys() 函數(shù)返回包含數(shù)組中所有鍵名的一個(gè)新數(shù)組。如果提供了第二個(gè)參數(shù),則只返回鍵值為該值的鍵名2011-10-10PHP編程文件處理類SplFileObject和SplFileInfo用法實(shí)例分析
這篇文章主要介紹了PHP編程文件處理類SplFileObject和SplFileInfo用法,結(jié)合實(shí)例形式分析了文件處理類SplFileObject和SplFileInfo的功能、定義、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-07-07PHP+redis實(shí)現(xiàn)微博的推模型案例分析
這篇文章主要介紹了PHP+redis實(shí)現(xiàn)微博的推模型案例,結(jié)合實(shí)例形式分析了php+redis實(shí)現(xiàn)微博推送與關(guān)注功能相關(guān)操作技巧,需要的朋友可以參考下2019-07-07PHP中header()函數(shù)的七種用法小結(jié)
我們在實(shí)際開發(fā)中經(jīng)常使用header()實(shí)現(xiàn)一些功能,這篇文章介紹關(guān)于header()的7中用法,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,需要的朋友可以參考下2023-08-08php實(shí)現(xiàn)復(fù)制移動(dòng)文件的方法
這篇文章主要介紹了php實(shí)現(xiàn)復(fù)制移動(dòng)文件的方法,實(shí)例分析了php實(shí)現(xiàn)針對(duì)文件的復(fù)制及移動(dòng)的技巧,需要的朋友可以參考下2015-07-07