如果db query A没有返回足够的结果,请运行查询B:如何优化?

时间:2010-08-20 14:43:38

标签: php mysql refactoring

我正在寻找一个好的设计模式或最佳实践来实现“此查询或其他查询”的情况,具有最佳性能和最小开销。

demans的商业逻辑/程序说“自Foo以来的所有项目”,除非返回少于三个项目,然后是“所有项目”。 我正在重构当前的代码,并且无法想出一个实现这种逻辑的好方法。

当前伪代码(Drupal / PHP):

<?php
$result = db_query(
'SELECT n.uid FROM og_ancestry oga ' .
'INNER JOIN node n on n.nid = oga.nid ' .
'WHERE oga.group_nid = %d AND n.created > %d GROUP BY n.uid ' .
'ORDER BY cnt DESC LIMIT %d', $group_nid, $since, $limit);


while ($row = db_fetch_array($result)) {
  $uids[] = $row['uid'];
}

if (count($uids) < 3) {
  $result = db_query(
    'SELECT n.uid FROM og_ancestry oga ' .
    'INNER JOIN node n on n.nid = oga.nid ' .
    'WHERE oga.group_nid = %d GROUP BY n.uid ' .
    'ORDER BY cnt DESC LIMIT %d', $group_nid, $limit);

  while ($row = db_fetch_array($result)) {
    $uids[] = $row['uid'];
  }
}
//...do something with the result.
?>

此代码感觉“不对”,首先是因为DRY:它包含相同的查询,只有一个小的区别。我可以通过更聪明的查询构建来改变它。

但更糟糕的是,我需要锤击数据库(查询非常繁重)才发现在超过一半的情况下,我需要丢弃结果并再次查询数据库。

你会如何处理这种情况?

3 个答案:

答案 0 :(得分:4)

如果如你所说,“在超过一半的情况下,我需要丢弃结果并再次查询数据库”,那么你最好的选择可能是运行 第二次查询然后在本地评估结果数据集,如果合适,丢弃记录。这实际上更多的是移动复杂性而不是降低复杂性,但至少只有一次数据库之旅。

如果你ORDER BY n.created DESC,过滤可以简单地查看第三条记录,如果它早于foo,那么你就完成了;否则,你需要在foo之前找到第一条记录并丢弃它和后续记录。

答案 1 :(得分:2)

您可以使用单个CASE/WHEN query查看第一个查询是否返回足够的内容。如果是这样,请使用THEN块。如果不使用ELSE块。这样可以节省第二次往返数据库。

答案 2 :(得分:0)

ORDER BY n.created DESC, cnt DESC LIMIT 3的一个查询是否有效?它将首先获得最近创建的项目,并返回不超过3个。它与完全相同与上面的相同,但它非常接近......