2012-11-26 27 views
9

PDO準備文を使用後に解放する必要がありますか?そしてもしそうなら、どうですか?具体的には、私はMySQLについて質問しています - あなたはどうすればよいでしょうか、あなたはPDOでもDEALLOCATE PREPAREに電話してください。 (編集:明確にするために、この質問はエミュレートされた準備について言及していませんが、実際の準備です)PDO準備文を解放する(DEALLOCATE PREPARE)

また、これは結果セット(大きな場合)を解放しますか?

説明:

私はこれが何を、いつ、unset($stmnt);は異なるだろうfの場合を不思議に私を導いた

$stmnt = $db->prepare($sql); 
$stmnt->execute($aParams); 
$stmnt = null; 

の線に沿ってコードを見たことがありますか?

マニュアルは、クエリを調製する場合

は、データベースは、分析コンパイル及び がクエリを実行するための計画を最適化することを示しています。 [...]準備された ステートメントを使用することにより、アプリケーションは analyze/compile/optimizeサイクルの繰り返しを回避します。

これは、ステートメントの割り当てを解除する必要がある傾向があり、MySQLには機能があります。だから、

  1. あなたはDEALLOCATE PREPAREを呼び出すことができますし、あなたはそれをどのように行うべき
  2. 誰かが、mysql_とmysqli_の "free_result"と同じようにnullを設定する(または設定を解除する)ことを確認できますか?
  3. すぐに実行されるのですか、またはガベージコレクタが起動するのを待機していますか? (あなたが大量のメモリ使用量を持ち、スペースを必要としない限り)完全性については

、「free_result」とmysqli_()のための「クローズ」機能を参照する別のSO questionは、文を解放することは、実際に時間を追加することを示唆しています。しかし、 "free_result"は、準備されたSQL文をキャッシュしておくこととは異なります。

+0

エミュレートされた準備を特にオフにしていますか?デフォルトでは、プリペアドステートメントはドライバでエミュレートされ、リクエストの最後に(すべてがGCdの場合)解放されます。とにかくそれらを意図的に解放するのは何でしょうか?可能であれば、用意されたステートメントを再利用することで、パフォーマンスが向上します。ポイント3をアドレス指定するには、[ステートメントが破棄されたときにfree_resultが呼び出されます](http://lxr.php.net/xref/PHP_5_4/ext/pdo_mysql/mysql_statement.c#55)(未設定、リクエストの終了など) - テストなしでは、私はdtorsがすぐに呼び出されると信じています。 – Leigh

+0

はい、私は準備をエミュレートしていません - 申し訳ありませんが、質問で明確にすべきでした(そうでなければ質問は無意味です)。なぜそれを解放するのですか?その接続には一度も使用されないステートメントがいくつか存在するため、それらも解放される可能性があります(最適化はキャッシュされません)。再利用された人は私が(もう必要がなくなるまで、それを解放する方法について同じ質問が適用されます)。 – Robbie

答えて

3

使用後にPDO準備ステートメントを解放する必要がありますか?そしてもしそうなら、どうですか?

MySQLのコンテキストでは、いいえ、なぜですか?

PDO emulates prepared statements by default。これは、PDO自体がパラメータの置換、エスケープなどを行い、ネイティブプリペアドステートメントを使用する代わりに、SQLのチャンクをラインに送信することを意味します。

あなたもunbuffered queriesを使用しているない限り、あなたはそれをオンにすることができますが、あなたはまだ明示する必要はありませんは、ハンドルを閉じます。ステートメントハンドルを有効範囲外にするかヌルに設定するだけでは、ではなく、カーソルを閉じることができます。繰り返しますが、これはのみで、バッファリングされていないクエリを使用している場合は問題になります。そうでない場合は、スコープを外に出すかnullに設定するだけで、ハンドルをきれいに閉じることができます。

また、DEALLOCATE PREPAREにリンクしています。その構文はを手動で入力する場合はになります。を呼び出すと、SQL文字列でPREPAREが呼び出されます。これはMySQL C-level API-based prepared statementsより完全に完全に別のアクションです。これはPDO_MYSQLが使用しているものです。 (さて、あなたはmysqlndを使用しているかもしれませんが、事実上同じことです)

+0

申し訳ありません - 私は実際に準備されたステートメントを使用することに言及していることを明確にすべきでした。私はソースを見つけることができませんが、 "prepare()"がデータベースに "PREAPRE"を呼び出すことを読むことを覚えています - それはDEALLOCATE PREPAREと呼ぶべきかという疑問につながります。私はあなたが主張するようにPREPAREが呼び出されていないことをテストするつもりです - 私はすべてのクエリを仕事中に記録しているので、私はあなたに戻ってきます)。私はクエリをバッファリングしていません。応答に感謝 - 私は一日後にフォローアップします。 – Robbie

+0

Cコード(およびmysqlnd)が使用するワイヤレベルのAPIを扱うときに実際の 'PREPARE' SQL * anywhere *が表示されたら、私は帽子を食べます。それはそうだろう... *間違っている* ...私の心は、何週間も間違っていたことについて吹き飛ばされるだろう。 – Charles

+2

帽子を食べる必要はありません - 私はログをチェックしました。 PREPAREは表示されませんが、prepare()を呼び出すとリンクしたCレベルAPIに適合します。また、mysql_stmt_close(stmt))もすぐに呼び出されるように見えます。おそらくPHPでstmntを "null"に設定している(明らかに制限されたテストですが、常にログに続く "stmt close")。ポインタをありがとう - 私はそれを正しくやっている東に残ります。 – Robbie

0

はい。 prepareステートメントを実行したら、NULLに設定するか、unset()を使用します。

複数のクエリと大きなデータベースを持つスクリプトでは、これが違いになります。

$before = memory_get_usage(); 
$stmt = NULL; 
die(memory_get_usage() - before); 

私にとって、これは後でスクリプトをクラッシュさせた20MBのメモリを節約しました。

+0

質問はpdo文ではなく、準備された文についてです。 20MBを節約するには、バッファされていないクエリを使用していたはずです –