什么更快,db调用或使用数组?

时间:2015-05-18 14:14:01

标签: php mysql optimization

在我维护的网站中,我需要两次查询同一个表(文章),每个类别的文章一次。 AFAIT基本上有两种方法可以做到这一点(也许有人可以提出更好的第三种方式?):

  1. 执行两次数据库查询,这意味着数据库服务器必须对整个表进行两次排序。在每次查询之后,我迭代光标以在页面上为列表条目生成html
  2. 只执行一次查询并取出所有记录,然后将它们分成两个单独的数组。在此之后,我必须分别迭代每个数组,以生成HTML
  3. 所以这就是:

    $newsQuery = $mysqli->query("SELECT * FROM articles WHERE type='news' ");
    while($newRow = $newsQuery->fetch_assoc()){
      // generate article summary in html
    }
    // repeat for informational articles
    

    vs this:

    $query = $mysqli->query("SELECT * FROM articles ");
    $news = Array();
    $info = Array();
    while($row = $query->fetch_assoc()){
      if($row['type'] == "news"){
        $news[] = $row;
      }else{
        $info[] = $row;
      }
    }
    // iterate over each array separate to generate article summaries
    

    记录集不是很大,当前< 200并且可能会增长到1000-2000。两种方法之间的时间是否存在显着差异,如果是这样,哪一种更快?

    (我知道这整个事情看起来非常低效,但它是一个编码不好的网站,我继承并且必须在没有预算的情况下处理重构整个事情......)

    我用PHP编写,没有框架:(,在MySql db上。

    修改

    我刚刚意识到我遗漏了一个主要细节。在网站的给定页面上,我们将一次显示(并因此从数据库中检索)不超过30条记录 - 但这里有捕获:15篇信息文章和15篇新闻文章。在每个页面上,我们会拉出下一个15种。

3 个答案:

答案 0 :(得分:1)

你知道你可以在数据库中排序吗?

SELECT * FROM articles ORDER BY type

答案 1 :(得分:1)

修改

由于对问题所做的更改,我正在更新我的答案,以解决新发布的要求:“新闻”15行,“非新闻”15行。

问题的要点是相同的“哪个更快......一个查询到两个单独的查询”。答案的要点保持不变:每个数据库往返都会产生开销(额外的时间,尤其是通过网络连接到单独的数据库服务器),所以在其他条件相同的情况下,减少数据库往返次数可以提高性能。

新要求确实不会对此产生影响。新发布的需求真正影响的是实际的查询以返回指定的结果集。

例如:

( SELECT n.*
    FROM articles n 
   WHERE n.type='news'
   LIMIT 15 
)
UNION ALL
( SELECT o.*
    FROM articles o 
   WHERE NOT (o.type<=>'news')
   LIMIT 15 
)

将该语句作为单个查询运行将需要更少的数据库资源,并且更快而不是运行两个单独的语句,并检索两个不同的结果集。

我们没有提供任何关于type的其他值的指示,因此这里提供的语句只涉及两个一般类别的行:具有type='news'的行和所有其他行对type有其他价值。

该查询假定type允许NULL值,并且我们想要返回类型为NULL的行。如果不是这样,我们可以将谓词调整为

 WHERE o.type <> 'news'

或者,如果我们感兴趣的type有特定值,我们可以在谓词中指定

 WHERE o.type IN ('alert','info','weather')

如果需要“分页”......“接下来的15”,我们看到应用的典型模式,LIMIT 30,15可能效率低下。但是这个问题并不是要求提高“分页”查询的效率,而是要求运行单个语句或运行两个单独的语句是否更快。

这个问题的答案仍然是一样的。

原始回答

每次数据库往返都有开销。就数据库性能而言,对于小型集合(如您所描述的),您最好使用单个数据库查询。

缺点是您正在获取所有这些行并实现数组。 (但是,看起来这就是你在任何一种情况下使用的方法。)

如果您在显示的两个选项之间进行选择,请使用单个查询。那会更快。

就不同的方法而言,它实际上取决于您对这些阵列的处理方式。

您实际上可以让数据库使用ORDER BY子句以指定的顺序返回行。

首先获取所有'news'行,然后是非'news'的所有内容,您可以

ORDER BY type<=>'news' DESC

这是MySQL的缩写,符合ANSI标准:

ORDER BY CASE WHEN t.type = 'news' THEN 1 ELSE 0 END DESC

您可以在输出每一行时从光标中获取,而不是获取每一行并将其存储在数组中,例如。

while($row = $query->fetch_assoc()) {
   echo "<br>Title: " . htmlspecialchars($row['title']);
   echo "<br>byline: " . htmlspecialchars($row['byline']);
   echo "<hr>";
}

答案 2 :(得分:0)

处理这种情况的最佳方法是亲自测试。你现在有多少记录并不重要。你可以模拟你喜欢的任何数量,这从来都不是问题。此外,1000-2000实际上是一小组数据。

我有点不明白你为什么要两次迭代所有记录。您不应该以任何方式检索查询中的所有记录,而只需要使用一小部分记录。在您管理文章的典型网站中,每页最多10条记录。任何用户都不会以一种您必须立即提取所有记录的方式浏览2000篇文章。利用分页和智能查询。

  

//分别迭代每个数组以生成文章摘要

这不是你的意思,但有些东西告诉我这些数据也应存储在数据库中。我真的希望你不会为每一个页面点击动态生成文章摘录。

对我而言,这听起来更像是一个糟糕的建筑设计而不是其他任何东西......

PS:我认为数据库数据的排序/排序/过滤应该在数据库服务器上完成,而不是在应用程序本身中完成。您可以通过执行单个查询来节省一些流量,但如果您一次传输过多数据,那么它将无法帮助您,但您仍然无法使用。