1

次のコードは、私の実際のコードのモックアップです。myFunctionが呼び出されると、パフォーマンスが大幅に低下します。myTableは数百行以内ですが、myFunctionを呼び出すと実行時間が最大10秒長くなります。すでにそのテーブルにアクセスしているループ内のテーブルの行にアクセスしようとすると、本質的に何か問題がありますか?

<select>
<?php
  $stmt = SQLout ("SELECT ID,Title FROM myTable WHERE LEFT(Title,2) = ? ORDER BY Title DESC",
                   array ('s', $co), array (&$id, &$co_title));
  while ($stmt->fetch()) {
    if (myFunction($id))  // skip this function call and save 10 seconds
      echo '<option value="' . $co_title . '">' . $co_title . '</option>';
  }
  $stmt->close();


function myFunction ($id) {
  $stmt = SQLout ("SELECT Info FROM myTable WHERE ID = ?",
                   array ('i', $id), array (&$info));
  if ($stmt->fetch()) {
    $stmt->close();
    if ($info == $something)
      return true;
  }
  return false;
}
?>

SQLoutは基本的に次のとおりです。

$sqli_db->prepare($query);
$stmt->bind_param;
$stmt->execute();
$stmt->bind_result;
return $stmt;
4

3 に答える 3

2

あなたがしていることは、「N+1クエリ」問題と呼ばれることもあります。最初の(外部)クエリを1回実行すると、N行が返されます。次に、最初のクエリによって返された行ごとに1つずつ、N個の従属クエリを実行します。したがって、N+1クエリ。それは多くのオーバーヘッドを引き起こします。

SQLで「何か」の条件を適用できれば、パフォーマンスは大幅に向上します。

$stmt = SQLout ("SELECT ID,Title FROM myTable 
    WHERE LEFT(Title,2) = ? AND Info = ... ORDER BY Title DESC",
    array ('s', $co), array (&$id, &$co_title));

一般に、外部クエリに一致する行数に依存するループでクエリを実行することはお勧めできません。外部クエリが1000000行に一致する場合はどうなりますか?つまり、ループ内の100万のクエリが、この単一のPHPリクエストに対してデータベースにヒットします。

今日、外部クエリが3行にしか一致しない場合でも、このようにコードを設計したという事実は、6か月後、予測できない時期に、たとえあなたのコードは変更されません。クエリの数は、コードではなくデータによって決まります。

たとえば、「何か」の条件が複雑でSQL式で表現できない場合など、実行していることを実行する必要がある場合があります。ただし、他のすべての場合は、このN+1クエリのパターンを回避するようにしてください。

于 2013-03-13T19:41:22.987 に答える
0

したがって、テーブルに「数百行」がある場合、最初のクエリで返される行数に応じて、myFunctionを数百回呼び出す可能性があります。

最初のクエリが返す行数をチェックして、期待どおりであることを確認します。

その後、myTable.IDにインデックスがあることを確認します。

その後、システム/サーバーレベルの問題の調査を開始します。低速のシステム、たとえばラップトップのハードドライブでは、1秒あたり10回のクエリで十分な場合があります。

于 2013-03-13T19:41:39.637 に答える
0

次のようなものを試してください。

  $stmt = SQLout ("SELECT ID,Title, Info FROM myTable WHERE LEFT(Title,2) = ? ORDER BY Title DESC",
                   array ('s', $co), array (&$id, &$co_title, &$info));
  while ($stmt->fetch()) {
    if (myFunction($info))  // skip this function call and save 10 seconds
      echo '<option value="' . $co_title . '">' . $co_title . '</option>';
  }
  $stmt->close();

function myFunction ($info) {
  if ($info == $something)
    return true;
  }
  return false;
}
于 2013-03-13T19:49:20.157 に答える