8

この問題でクエリをループすることについて、社内で内部討論を行っています。

$sql = "
  SELECT foreign_key
  FROM t1";

foreach(fetchAll($sql) as $row)
{
  $sub_sql = "
    SELECT *
    FROM t2
    WHERE t2.id = " . $row['foreign_key'];

  foreach(fetchAll($sub_sql) as $sub_row)
  {
    // ...
  }
}

次のような sql 結合を使用する代わりに:

$sql = "
  SELECT t2.*
  FROM t2
  JOIN t1
  ON t1.foreign_key = t2.id";

foreach(fetchAll($sql) as $row)
{
  // ...
}

これに関する追加情報、データベースは巨大で、何百万行もあります。

もちろん、私はこの質問に対する答えを探しましたが、誰もこれに良い方法で答えることができず、多くの賛成票を投じて、一方の方法が他方の方法よりも優れていることを確信させてくれます。

質問

これらの方法の1つが他の方法よりも優れている理由を誰かが説明できますか?

4

2 に答える 2

11

このjoin方法は、クエリをデータベースにやり取りするオーバーヘッドを削減するという理由だけで、一般的に優れていると考えられています。

テーブルに適切なインデックスがある場合、2 つの方法の基本的なパフォーマンスは似ています。つまり、どちらのメソッドも適切なインデックスを使用して結果を取得します。

データベースの観点からは、このjoin方法ははるかに優れています。これにより、データ ロジックが 1 か所に統合​​され、コードがより透過的になります。また、データベースは、アプリケーション コードでは明らかではない最適化を行うことができます。

于 2013-08-23T14:12:06.033 に答える
8

ドライバーのオーバーヘッドのため、ループははるかに効率が悪い

これは私が回答した別の質問に似ていますが、cv しないほど異なります。私の完全な答えはここにありますが、要点を要約します。

データベースに接続するたびに、次の 3 つの手順が実行されます。

  1. データベースへの接続が確立されます。
  2. データベースに対する 1 つまたは複数のクエリが実行されます。
  3. 処理のためにデータが返されます。

ループ構造を使用すると、ドライバー要求で追加のオーバーヘッドが発生することになり、単一の要求と単一の戻りではなく、ループ サイクルごとに要求と戻りが発生します。ループされたクエリが単一の大きなクエリよりも長くかからない場合でも (MySQL 内部には完全な反復ループの使用を防ぐために多くのショートカットが組み込まれているため、これはほとんどありません)、単一のクエリの方が高速であることがわかります。ドライバーのオーバーヘッド。

を使用せずにループを使用するTRANSACTIONSと、リレーショナル データの整合性の問題が発生し、ループ サイクル間で反復するデータに他の操作が影響することにも気付くでしょう。トランザクションを使用すると、データベースが 2 つの永続的な状態を維持する必要があるため、オーバーヘッドが増加します。

于 2013-08-23T14:16:16.607 に答える