0

プログラミングしているサイトに問題があります。ページと子ページがあるサイト セクションでは、処理が少し遅くなります。特にこのセクションには多くの mySQL クエリがあります。同時に実行されるクエリが 20 を超えているため、何かが表示されるまで最大 5 秒待たなければなりません。

この質問を読みましたページの読み込みごとに20個のSQLクエリは本当に多く考慮されていますか? そして、私には実際に問題があることがわかりました...そしてmadlepの答えは、すべてのページのforeach内でデータベースにクエリを実行し、その子を探しているこのN + 1の状況に言及しました。

以下に例を示します (ちなみに、私は 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 ループの外で子ページを取得するにはどうすればよいかということです。すべてが動的に行われるため、これを処理するには柔軟なアプローチが必要です。

4

1 に答える 1

1

まず、比較的少数のアイテム (Web ページなど) を追跡しているため、データベース クエリを発行するのではなく、階層全体を保持し、RAM でクエリできるキャッシュされたデータ構造からこれらを取得します。アプリの起動時にこのキャッシュ構造を構築し、ページを頻繁に変更する場合は、タスク/ジョブを介して定期的に再構築することができます。ただし、これがオプションでない場合は、コード ロジックを使用して複数のクエリを実行するのではなく、単一の SET OPERATION として完全なレコードセットを返す SQL クエリ全体を実際に書き直す必要があります。ORM には N+1 を処理する方法があるかもしれませんが、通常、N+1 を回避するためにクエリを書き直すか、テーブルを再構築するように指示されます。

キャッシュ構造の例 次の形式のディクショナリ: CurrentPageId、ParentPageId

ParentPageId が null のページは、ルート レベルのページです。

于 2013-05-22T19:44:21.007 に答える