代码之家  ›  专栏  ›  技术社区  ›  berkes

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

  •  5
  • berkes  · 技术社区  · 14 年前

    我正在寻找一个好的设计模式或最佳实践,以实现“要么是这个查询,要么是另一个查询”的情况,以最佳的性能和最少的开销。

    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.
    ?>
    

    这段代码感觉“不正确”,首先是因为干燥:它包含相同的查询,有一个微小的差异。我可以通过更智能的查询构建来改变这一点。

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

    你将如何处理这样的案件?

    3 回复  |  直到 14 年前
        1
  •  4
  •   Carl Manaster    14 年前

    如果,如您所说,“在超过一半的情况下,我需要放弃结果,再次查询数据库”,那么您最好的选择可能是运行 只有 第二个查询,然后在本地计算结果数据集,如果合适的话丢弃记录。与降低复杂性相比,移动复杂性实际上更重要,但至少只有一次访问数据库的过程。

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

        2
  •  2
  •   Gordon Haim Evgi    14 年前

    你可以用单人间 CASE/WHEN query 以查看第一个查询是否返回足够的值。如果是,请使用then块。如果不使用else块。这将节省您到数据库的第二次往返。

        3
  •  0
  •   Borealid    14 年前

    有人会问 ORDER BY n.created DESC, cnt DESC LIMIT 3 工作?它将首先获取最近创建的项目,并返回不超过3个。它不是 确切地 和你上面的一样,但很接近…