如何查找相关页面而不在循环内查询?

时间:2013-05-22 19:30:07

标签: mysql sql performance webpage

我正在编程我正在编程的网站。在我有网页和子页面的网站部分,情况有点慢。 我在本节特别提到了很多mySQL查询,同时执行的查询超过20个, 让我等到5秒,直到出现任何事情。

我读了这个问题Is 20 SQL Queries per page load really considered a lot?并且发现我确实遇到了问题...... madlep的答案提到了这个N + 1情况,我在每个页面的foreach中查询数据库,寻找它的子节点。

这是一个例子(顺便说一下,我正在使用Laravel):

 $pages = Page::where('slug', '=', $slug)->get(array('id', 'title', 'slug'));
 foreach ($pages as $page) {
    $children = Page::where('parent_id', '=', $page->id)->get(array('id', 'title', 'slug'));
    foreach ($children as $child) {
        $grandChildren = Page::where('parent_id', '=', $child->id)->get(array('id', 'title', 'slug'));
    }
 }

作为一个新手,我想找到一个更好的方法来处理这个问题,减少页面查询。

问题是:如何在foreach循环之外获取子页面?一切都是动态完成的,所以我需要一种灵活的方法来处理这个问题。

1 个答案:

答案 0 :(得分:1)

首先,由于您正在跟踪相对较小的项目(例如Web页面),因此我将从包含整个Heirarchy的缓存数据结构中提取这些内容,并且可以在RAM中查询而不是发出数据库查询。您可以在应用程序启动时构建此缓存结构,并且如果您经常更改页面,则可以通过任务/作业定期重建。但是,如果这不是一个选项,您确实需要重新编写一个完整的SQL查询,该查询将完整记录集作为单个SET OPERATION执行,而不是使用代码逻辑执行多个查询。您的ORM可能有办法处理N + 1,但通常它们会告诉您重新编写查询或重组表以避免N + 1.

缓存结构示例 字典形式为:CurrentPageId,ParentPageId

ParentPageId为null的任何页面都是根级页面。