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 行。然后,您运行 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 行怎么办?这意味着循环内的一百万个查询将针对这个单个 PHP 请求访问您的数据库。

即使今天外部查询只匹配 3 行,您以这种方式构建代码的事实意味着从现在起六个月后,在某个不可预测的时间,将会有一些搜索导致巨大的开销,即使您的代码不变。查询的数量是由数据驱动的,而不是代码。

有时有必要做你正在做的事情,例如“某事”条件很复杂,不能用 SQL 表达式表示。但是您应该尝试在所有其他情况下避免这种 N+1 查询模式。

于 2013-03-13T19:41:22.987 回答
0

因此,如果表中有“几百行”,您可能会调用 myFunction 几百次,具体取决于第一个查询中返回的行数。

检查第一个查询返回的行数,以确保它符合您的期望。

之后,确保您在 myTable.ID 上有一个索引。

之后,我将开始研究系统/服务器级别的问题。在较慢的系统上,比如笔记本电脑硬盘,每秒 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 回答