2013-06-26 87 views
15

我總是覺得PHP/MySQL緩衝和非緩衝查詢之間的區別是,緩衝(默認)將所有數據加載到結果集變量中和然後您可以開始使用它們,而不緩衝一次加載一行。PHP + MySQL:緩衝和非緩衝查詢之間的區別

假設你跑SELECT * FROM sometable,然後做$result = $db->query($query);,$result將包含所有的行和補充信息,如行數。所以如果你在一個100MB的數據庫上做了這個工作,你會發現$result在沒有索引的情況下佔用了大約100MB)。

不過,我碰到這個SO overflow question其中一部分表示緩衝查詢:

[的]結果將包含行的一些緩衝區實現有關。它可能是100行或更少或更少。所有列都爲每行返回;當您最終獲取更多行時,客戶端會向服務器請求更多行。這可能是客戶用完或可能會搶先完成的情況。

這是對的嗎,還真有一些緩衝嗎?如果是這樣的話,當處理大型結果集時,我們通常不需要擔心PHP內存不足嗎?這很奇怪,因爲我一直在40MB測試表上運行一些測試緩衝查詢,而PHP總是報告大約5MB的峯值內存使用量。

最後,作爲一個經驗法則,你什麼時候選擇無緩衝緩衝?你能舉個例子嗎?

謝謝。

(我正在使用MySQLi,我假設主體是一樣的)。

編輯:我現在讀了更多,我更加困惑。在http://php.net/manual/en/mysqli.quickstart.statements.php它說

在語句執行結果可以立即被檢索到客戶端緩衝或逐行讀取。客戶端結果集緩衝允許服務器儘早釋放與語句結果相關的資源。一般來說,客戶端是耗時較慢的結果集。因此,建議使用緩衝結果集。 mysqli_query()結合語句執行和結果集緩衝。

PHP應用程序可以通過緩衝結果自由導航。導航速度很快,因爲結果集保存在客戶端內存中。請記住,客戶端擴展通常比擴展服務器更容易。

而就http://php.net/manual/en/mysqli-result.fetch-all.php它說:

作爲mysqli_fetch_all()返回的所有行作爲在單個步驟中的陣列,其可以消耗比一些類似的功能,如mysqli_fetch_array(),多個存儲器,其從結果集中一次只返回一行。此外,如果您需要遍歷結果集,則需要一個循環構造,這會進一步影響性能。由於這些原因,mysqli_fetch_all()應該僅用於那些將獲取的結果集發送到另一個層進行處理的情況。

這似乎有些矛盾。「客戶端結果集緩衝」和「消費結果集」之間有什麼區別?一個說他們被關在客戶端內存中,另一個則說是逐行讀取。如果整個事情被緩衝到PHP爲什麼最後一句話說如果你在一個步驟中將所有行作爲數組返回,它可能會消耗更多的內存?

+0

緩衝處理內部到SQL Server而不是PHP – Dave

+0

這是否涉及到我上面的編輯?如果你能在你的回答中向我解釋,我會接受它。謝謝。 – texelate

+1

它不應該被稱爲緩衝tbh它應該被稱爲結果緩存。 PHP將保存整個結果對象的一小部分,然後它必須從MySQL中取出其餘部分。我想不出任何人在php做客戶端的實例,除非這意味着PHP作爲MySQL的客戶端。 Mysql會進行內部查詢緩衝和緩存以加快查找速度,而不必進行全表讀取等操作。基本上,儘管在標準的mysql使用情況下,您不需要擔心它,只需讓它將它自己排序即可。 – Dave

回答

14

參見:http://php.net/manual/en/mysqlinfo.concepts.buffering.php

無緩衝的MySQL查詢,執行查詢,然後返回一個資源 而數據仍然在MySQL服務器上等待被取出。 這在PHP端使用較少的內存,但可以增加服務器上的負載 。除非完整的結果集是從服務器取得的否 進一步的查詢可以通過同一連接發送。無緩衝 查詢也可以稱爲「使用結果」。

以下這些特性應該在您希望只有有限的結果集或需要在讀取所有行之前知道返回的行數時使用緩衝查詢。當你期待更大的結果時,應該使用非緩衝模式。

緩衝查詢是默認的。

無緩衝舉例:

<?php 
$mysqli = new mysqli("localhost", "my_user", "my_password", "world"); 
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT); 

if ($uresult) { 
    while ($row = $uresult->fetch_assoc()) { 
     echo $row['Name'] . PHP_EOL; 
    } 
} 
$uresult->close(); 
?> 

希望這有助於

+0

好點。實際上,通過使用free_result()放棄結果資源,您可以在同一連接上使用多個準備好的語句/查詢。但是,這會阻止您從此結果集中獲取更多的元組/行。 –