以下代码是我的真实代码的模型。调用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;
答案 0 :(得分:2)
您正在做的事情有时被称为“N + 1查询”问题。您运行第一个(外部)查询1次,并返回N行。然后运行N个从属查询,第一个查询返回的每一行查询一个。因此N + 1查询。它会导致很多开销。
如果您可以在SQL中应用“something”条件,那么这将有更好的性能:
$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查询模式。
答案 1 :(得分:0)
因此,如果表中有“几百行”,则可能会调用myFunction几百次,具体取决于第一次查询中返回的行数。
检查首次查询返回的行数,以确保它符合您的期望。
之后,请确保myTable.ID上有索引。
之后,我将开始研究系统/服务器级问题。在速度较慢的系统上,比如一台笔记本电脑硬盘,每秒可以获得10次查询。
答案 2 :(得分: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;
}