【问题标题】:Efficient Foreach loop querying database高效的 Foreach 循环查询数据库
【发布时间】:2014-05-15 06:11:28
【问题描述】:

我在我的网站上显示图片及其详细信息,但是最近该网站的加载速度非常慢。

最主要的是这个 foreach 循环循环 100 次以在网格中显示 100 个帖子。运行需要 14 秒

foreach($posts as $post) {

            $hashtags[] = $this->HashTagsModel->get_hashtags($post["id"]);
            $author[] = $this->UserModel->get_user_details($post["user_id"]);
            $comment_count[] = $this->CommentModel->get_comments_count($post["id"]);
            $is_favourited[] = $this->FavouriteModel->is_favourited($post["id"]);
            $is_reposted[] = $this->RepostModel->is_reposted($post["id"]);
            $vote_status[] = $this->vote_status($post["id"]);
            $comments[] = $this->count_comments($post["id"]);

        }

如何以不同的方式执行此操作以提高效率?这在我们的网站数据库变得庞大之前就已经奏效了

任何帮助将不胜感激,

问候,

差点被解雇

【问题讨论】:

  • 好吧,如果你已经怀疑数据库增长是原因(你可能就在那里),那么你无法在 php 级别解决这个问题。您必须仔细查看 sql 语句、表,尤其是数据库中的索引定义!因此,我们要帮助您发布您的数据库结构和查询。
  • 100 个带有 7(+) 个子查询的帖子应该不会花费太多时间。我建议您逐个检查这 7 个函数中每一个的执行时间。我敢打赌,其中一个会导致大多数时间问题。

标签: php performance codeigniter loops foreach


【解决方案1】:

foreach 循环查询数据库的有效方法是不 foreach 查询数据库。这是因为您允许触发未知数量的查询,这将导致大量排队。如果突然添加了 5000 张图像怎么办,你会遍历它们吗?该查询将花费很长时间。

您有 $post["id"] 作为我假设的 where 变量,因此您可以通过在制定一系列帖子 ID 后执行单个查询来显着减少此过程,就像这样:

$postids = array();
foreach($posts as $post) {
    $postids[] = $post['id'];
}

// Selecting from 1 table
$query = 'SELECT * FROM hashtags WHERE id IN ('. implode(",", $postids) .')';

这将获取主题标签上的所有信息,其中 id 是您的 postid 之一。那只是 1 个表,您可能想要获取多个表,但不知道您的数据库结构我将是通用的,所以类似于:

// Selecting and joining data from multiple tables
$query = ' SELECT author.name, table.col FROM posts
LEFT JOIN author ON author.id = post.author_id
LEFT JOIN table ON table.id = post.table_id
WHERE posts.id IN IN ('. implode(",", $postids) .')';

要更准确有点困难。我认为加入表格会为您提供更好的结果,您甚至可以加入投票/cmets 的计数。如果这不可能,您可以查询与您的帖子相关的所有数据,然后在 PHP 中进行表述,然后您就可以确切地知道您有多少查询。例如,将模型更改为接受数组而不是单个帖子 ID,然后将“WHERE post_id = x”更改为“WHERE post_id IN (x)”,然后您可以执行以下操作:

$postids = array();
foreach($posts as $post) {
    $postids[] = $post['id'];
}

$hashtags = $this->HashTagsModel->get_hashtags($postids);
$author = $this->UserModel->get_user_details($postids);
$comment_count = $this->CommentModel->get_comments_count($postids);
$is_favourited = $this->FavouriteModel->is_favourited($postids);
$is_reposted = $this->RepostModel->is_reposted($postids);
$vote_status = $this->vote_status($postids);
$comments = $this->count_comments($postids);

这会使您的查询脱离循环,并且您知道只会有 7 个 SQL 查询,而不是查询 * 帖子。在 PHP 中,您将遍历每个数组的结果,以根据其 ID 将每个数组分配回帖子。

【讨论】:

  • 哇,这真的很有帮助!我将执行您的最后一个建议,但是我遇到了一些问题。对于作者,我发现它只返回作者发布的帖子的一个实例。例如,作者“B”发了 3 个帖子,但它只是退回了一次并填满了订单?有关如何执行此操作的任何建议?
  • 如果不知道您的模型是如何工作的以及您想要完成什么,就很难获得清晰的画面。如果您有 5 个帖子 ID,例如:[1, 3, 4, 4, 10],那么当您将其传递给 get_user_details 时,它将为每个帖子找到一个结果,但仅在帖子 ID 唯一的地方,所以id 4 只会返回一次。从逻辑上讲,顺序无关紧要,因为您将遍历结果并将数据附加到其他内容。我想知道为什么对于单个帖子,您需要知道该帖子的作者已经发布了 3 个其他帖子?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
相关资源
最近更新 更多