简体   繁体   English

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

[英]If db query A does not return enough results, run query B: how to optimize?

I am looking for a good design pattern, or best practice to achieve a situation of "either this query, or else that other query", with best performance and least overhead. 我正在寻找一种最佳的设计模式或最佳实践,以实现“此查询或其他查询”的情况,并获得最佳性能和最少的开销。

Business logic/program of demans says "all items since Foo", unless that returns less then three items, then "all items". Demans的业务逻辑/程序说“自Foo以来的所有项目”,除非返回少于三个项目,然后返回“所有项目”。 I am refactoring the current code, and cannot come up with a good way to achieve this logic. 我正在重构当前代码,无法提出一种实现此逻辑的好方法。

Current pseudo-code (Drupal/PHP): 当前的伪代码(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.
?>

This code feels "not right", first of all because of DRY: it contains the same query, with one minor difference. 这段代码感觉“不正确”,首先是因为DRY:它包含相同的查询,只是有一点点差异。 I can change that by a bit smarter query-building. 我可以通过更智能的查询构建来更改它。

But worse is the fact that I need to hammer the database (query is quite heavy) only to find out that in more then half of the cases, I need to throw away the result and query the db again. 但是更糟糕的是,我需要锤击数据库(查询非常繁琐),只是为了发现在一半以上的情况下,我需要丢弃结果并再次查询数据库。

How would you approach such a case? 您将如何处理这种情况?

If, as you say, "in more then half of the cases, I need to throw away the result and query the db again," then your best bet may be to run only the second query and then evaluate the resultant dataset locally, discarding records if appropriate. 如您所说,如果“在一半以上的情况下,我需要丢弃结果并再次查询数据库”,那么最好的选择可能是运行第二个查询,然后在本地评估结果数据集,并丢弃记录是否适当。 It's really more a matter of moving the complexity around than it is of reducing complexity, but at least there's just one trip to the database. 实际上,解决复杂性问题远比减少复杂性多,但至少只有一次数据库之旅。

If you ORDER BY n.created DESC , the filtering could simply look at the third record, and if it's earlier than foo, you're done; 如果您通过ORDER BY n.created DESC ,则过滤可以简单地查看第三条记录,如果它早于foo,那么您就完成了; otherwise, you need to find the first record before foo and discard it and subsequent records. 否则,您需要在foo之前找到第一个记录,并丢弃它和后续记录。

You could use a single CASE/WHEN query to see if the first query returns enough. 您可以使用单个CASE / WHEN查询来查看第一个查询是否返回足够的值。 If so, use the THEN block. 如果是这样,请使用THEN块。 If not use the ELSE block. 如果不使用ELSE块。 That would save you the second roundtrip to the database. 这样可以节省第二次往返数据库的时间。

Would one query with ORDER BY n.created DESC, cnt DESC LIMIT 3 work? 使用ORDER BY n.created DESC, cnt DESC LIMIT 3一个查询是否可以工作? It will get the most recently created items first, and return no more than 3 of them. 它将首先获取最近创建的项目,并返回不超过3个项目。 It's not exactly the same as what you have above, but it's pretty close... 它与上面的不完全相同 ,但是非常接近...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM