78

簡単な質問です。

ループでPDO::fetchAll()とPDO :: fetch()を使用することの間にパフォーマンスの違いはありますか(大きな結果セットの場合)?

違いがあれば、ユーザー定義クラスのオブジェクトをフェッチしています。

私の最初の知識のない仮定は、mysql_queryが実行できるのは1つだけであるのに対し、PDOは1つのステートメントで複数の操作を実行できるため、fetchAllの方が高速である可能性があるというものでした。ただし、私はPDOの内部動作についてほとんど知識がなく、ドキュメントにはこれについて何も記載されておらず、fetchAll()が単に配列にダンプされたPHP側のループであるかどうかがわかりません。

何か助けはありますか?

4

7 に答える 7

83

200kのランダムレコードを持つ小さなベンチマーク。予想どおり、fetchAllメソッドは高速ですが、より多くのメモリを必要とします。

Result :
fetchAll : 0.35965991020203s, 100249408b
fetch : 0.39197015762329s, 440b

使用したベンチマークコード:

<?php
// First benchmark : speed
$dbh = new PDO('mysql:dbname=testage;dbhost=localhost', 'root', '');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = 'SELECT * FROM test_table WHERE 1';
$stmt = $dbh->query($sql);
$data = array();
$start_all = microtime(true);
$data = $stmt->fetchAll();
$end_all = microtime(true);

$stmt = $dbh->query($sql);
$data = array();
$start_one = microtime(true);
while($data = $stmt->fetch()){}
$end_one = microtime(true);

// Second benchmark : memory usage
$stmt = $dbh->query($sql);
$data = array();
$memory_start_all = memory_get_usage();
$data = $stmt->fetchAll();
$memory_end_all = memory_get_usage();

$stmt = $dbh->query($sql);
$data = array();
$memory_end_one = 0;
$memory_start_one = memory_get_usage();
while($data = $stmt->fetch()){
  $memory_end_one = max($memory_end_one, memory_get_usage());
}

echo 'Result : <br/>
fetchAll : ' . ($end_all - $start_all) . 's, ' . ($memory_end_all - $memory_start_all) . 'b<br/>
fetch : ' . ($end_one - $start_one) . 's, ' . ($memory_end_one - $memory_start_one) . 'b<br/>';
于 2010-05-05T08:25:52.157 に答える
12

私がほとんど常に真実であることがわかったPHPについての1つのことは、自分で実装する関数は、ほとんどの場合、同等のPHPよりも遅くなるということです。これは、何かがPHPで実装されている場合、Cが持つ(PHPが記述されている)コンパイル時の最適化がすべて行われておらず、PHP関数呼び出しのオーバーヘッドが高いためです。

于 2010-05-05T04:39:38.947 に答える
11

「メモリーフットプリント」を測定する上記のすべてのベンチマークは、非常に単純な理由で実際には正しくありません。

PDOはデフォルトですべてのものをメモリにロードし、fetchとfetchAllのどちらを使用してもかまいません。バッファリングされていないクエリのメリットを実際に得るには、バッファリングされていないクエリを使用するようにPDOに指示する必要があります。

$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

その場合、スクリプトのメモリフットプリントに大きな違いが見られます

于 2017-03-01T14:44:23.803 に答える
9

@Arkh

// $data in this case is an array of rows;

$data = $stmt->fetchAll();


// $data in this case is just one row after each loop;

while($data = $stmt->fetch()){}


// Try using

$i = 0;

while($data[$i++] = $stmt->fetch()){}

メモリの違いは無視できるようになるはずです

于 2010-06-03T16:12:24.137 に答える
4

Mihai Stancuが言っていたように、fetchAllはfetch + whileを打ち負かしますが、メモリの違いはほとんどありません。

Result : 
fetchAll : 0.160676956177s, 118539304b
fetch : 0.121752023697s, 118544392b

正しく実行しているときに上記の結果が得られました:

$i = 0;
while($data[$i++] = $stmt->fetch()){
    //
}

したがって、fetchAllはより少ないメモリを消費しますが、fetch+whileの方が高速です。:)

于 2010-12-24T23:12:11.523 に答える
4

しかし、フェッチしたデータを配列に格納している場合、メモリ使用量は同じになりますか?

<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
// database to use
define('DB', 'test');
try
{
   $dbh = new \PDO('mysql:dbname='. DB .';host='. DB_HOST, DB_USER, DB_PASS);   $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
   $sql = 'SELECT * FROM users WHERE 1';
   $stmt = $dbh->query($sql);
   $data = array();
   $start_all = microtime(true);
   $data = $stmt->fetchAll();
   $end_all = microtime(true);

   $stmt = $dbh->query($sql);
   $data = array();
   $start_one = microtime(true);
   while($data = $stmt->fetch()){}
   $end_one = microtime(true);

   // Second benchmark : memory usage
   $stmt = $dbh->query($sql);
   $data = array();
   $memory_start_all = memory_get_usage();
   $data = $stmt->fetchAll();
   $memory_end_all = memory_get_usage();

   $stmt = $dbh->query($sql);
   $data = array();
   $memory_end_one = 0;
   $memory_start_one = memory_get_usage();
   while($data[] = $stmt->fetch()){
     $memory_end_one = max($memory_end_one, memory_get_usage());
   }

   echo 'Result : <br/>
   fetchAll : ' . ($end_all - $start_all) . 's, ' . ($memory_end_all - $memory_start_all) . 'b<br/>
   fetch : ' . ($end_one - $start_one) . 's, ' . ($memory_end_one - $memory_start_one) . 'b<br/>';
}
catch ( PDOException $e )
{
   echo $e->getMessage();
}
?>

Result : 
fetchAll : 2.6941299438477E-5s, 9824b
fetch : 1.5974044799805E-5s, 9824b
于 2012-05-28T13:04:10.840 に答える
2

私はこれが古いトピックであることを知っていますが、私は同じ質問をしているこれに出くわします。私自身の単純な「ベンチマーク」を実行し、他の人がここに書いたものを読んだ後、これは正確な科学ではなく、高品質で軽いコードを書くように努力する必要がある一方で、最初に多くの時間を無駄にする意味はないという結論に達しましたプロジェクトの。

私の提案は次のとおりです。コード(ベータ版?)をしばらく実行してデータを収集してから、最適化を開始します。

私の単純なベンチマーク(テストされた実行時間のみ)では、両方の方法で5%から50%の間で変化する結果が得られました。同じスクリプトで両方のオプションを実行しますが、最初にfetch +を実行すると、fetchallよりも高速であり、その逆も同様です。(私はそれらを1回実行し、数百回実行して中央値と平均値を取得してから比較する必要があることを知っていますが、最初に述べたように、私の場合は開始するには時期尚早であると結論付けました。)

于 2012-05-02T23:43:00.723 に答える