web-dev-qa-db-ja.com

mysqli_store_result()とmysqli_use_result()の比較

質問

mysqli::store_result()mysqli::use_result() の違いは何ですか?

物語

あいまいなドキュメント

PHP.netのドキュメントは、この2つの違いについて非常にあいまいなようです。 mysqli::use_result() -pageはコードサンプルを提供せず、 mysqli::multi_query() -pageにリンクしてそれらを探します。そのページでは、次のコードサンプルが提供されています(完全なコードについては、ページを参照してください)。

/* store first result set */
if ($result = $mysqli->store_result()) {
    while ($row = $result->fetch_row()) {
        printf("%s\n", $row[0]);
    }
    $result->free();
}
/* print divider */
if ($mysqli->more_results()) {
    printf("-----------------\n");
}

mysqli::store_result() -pageは、1つの例外を除いて、同じコードサンプルを正確に使用します。

/* store first result set */
if ($result = $mysqli->use_result()) {

ええと... store_resultuse_resultになりました。上記のコメントでも「store」と表示されていることに注意してください。

さらに混乱する

コードのサンプルを見て、私は考えました。 「大丈夫、それはエイリアスです」。ちょっと待って!ドキュメントには次の説明があります。

それらは2つの異なるもののように見え、エイリアスのようには持っていません。よく見てみると、 mysqli::use_result() -page:$result->free();のコードサンプルにさらに別の例外があることがわかりました。$result->close();になりました。しかし、真実を見つけるための私の期待はすぐに打ち砕かれた後、2番目のコードサンプルの同じページ(手順上の同等のもの)でmysqli_free_result($result);が使用され、予想されたmysqli_close_result($result);

33
Avaq

mysqli::store_result()はMySQLサーバーから結果セット全体をフェッチし、mysqli::use_result()は行を1つずつフェッチします。

これは、リンクした_mysqli::use_result_のドキュメントでも言及されています。

Mysqli_use_result()関数はデータベースから結果セット全体を転送しないため、mysqli_data_seek()などの関数を使用してセット内の特定の行に移動することはできません。この機能を使用するには、mysqli_store_result()を使用して結果セットを保存する必要があります。クライアント側で多くの処理が実行される場合はmysqli_use_result()を使用しないでください。これによりサーバーが拘束され、他のスレッドがデータのフェッチ元のテーブルを更新できなくなるためです。

サーバーからすべての行を一度に読み取らないという正当な理由がない限り、通常は常にmysqli::store_result()を使用できます。

37
ThiefMaster

use_resultnbufferedの結果を返します。

store_resultbufferedの結果を返します。

15
Neal

この詳細は、配列または列挙子を介した取得をサポートする言語からここに来る人々を助けるかもしれないと思います。それがまさにその違いだからです。

.NETの場合、 GetDirectories (store_results)と EnumerateDirectories (use_results)(およびFile/DbResult/CSV解析/同等のXML解析)。

列挙型のバリアントは、より少ない(PHP)クライアントメモリを使用し、現在の行の処理中にバックグラウンドで非同期に次の行をフェッチし、より多くのメモリと処理時間の両方をクライアント側で有効にします。 (結果セットが完全に送信されていないため)(SQL)サーバーのリソースをより長く消費することを犠牲にして。

次に、get/array方法は1回のブロック操作でデータを取得し、DBメモリをより早く解放するためにクライアント側のメモリをより多く消費します。

個人的には、実際に(クライアント)メモリの問題が発生しない限り、列挙子以外の方法がデフォルトになります。

.NETでは、2/3 GiB x32プロセスの制限に達した場合、列挙子の方法を使用する必要があります。ここでは、ファイルの特定のEnumerateLinesが重要です。DBの結果では、 A 2 GiB DB結果は、wayフィルタリング不足(クエリでさらにフィルタリングを実行)または多数のBlob(可能な場合は、少しずつロードするか、ブラウザーでhttpハンドラーを介して取得する必要があります)。

0
Christopher