6

現在、 paginate_by_sqlメソッドを使用してページ化するコレクションを構築するwill_paginateの実装があります。total_entriesのカスタムクエリがありますが、これは非常に複雑で、DBに大きな負荷をかけます。したがって、ページネーションからtotal_entriesを完全に削除したいと思います。

言い換えると、「前へ1 [2] 3 4 5次へ」の典型的なページネーション表示の代わりに、「次へ-前へ」ボタンのみが必要です。しかし、私たちはいくつかのことを知る必要があります。

  1. 前のリンクを表示しますか?もちろん、これは、現在の選択で表示されているレコードより前に存在するレコードの場合にのみ発生します。
  2. 次のリンクを表示しますか?コレクションの最後のレコードが表示されている場合、これは表示されません。

ドキュメントから

:total_entriesを指定しない場合、行をカウントするためのクエリが自動的に生成されます。この生成されたSQLで問題が発生した場合は、アプリケーションで手動でカウントを実行することをお勧めします。

したがって、最終的に理想的な状況は次のとおりです。

  • データベースに過度の負荷がかかるため、total_entriesカウントを削除します
  • ナビゲートするために次/前のボタンのみを使用してセミページネーションで一度に50レコードを表示し、使用可能なすべてのページ番号を表示する必要はありません
  • それに応じて次のボタンと前のボタンのみを表示します

誰かが同様の問題に取り組んだり、解決策について考えたことはありますか?

4

1 に答える 1

15

will_paginate がエントリ数を計算するという非常にひどい仕事をすることがよくあります。特に、カウント SQL ジェネレータを混乱させる結合が含まれている場合はそうです。

単純な prev/next メソッドだけが必要な場合は、データベースから N+1 個のエントリを取得しようとするだけで、最後のページよりも N 個以下しか得られない場合。

例えば:

per_page = 10
page = 2

@entries = Thing.with_some_scope.find(:all, :limit => per_page + 1, :offset => (page - 1) * per_page)

@next_page = @entries.slice!(per_page, 1)
@prev_page = page > 1

これを必要とするさまざまなモデルに含めることができるモジュールに簡単にカプセル化したり、コントローラー拡張を作成したりできます。

これは、デフォルトの will_paginate メソッドよりもはるかにうまく機能することがわかりました。

唯一のパフォーマンスの問題は、テーブルのサイズによっては問題になる可能性がある MySQL の制限です。

何らかの理由で、MySQL で小さな LIMIT を使用してクエリを実行するのにかかる時間は、OFFSET に比例します。実際には、データベース エンジンは、特定のオフセット値までのすべての行を読み取り、期待どおりにスキップせずに、次の LIMIT 行を返します。

OFFSET 値が 100,000 以上の範囲にある大規模なデータセットの場合、パフォーマンスが大幅に低下することがあります。これがどのように明らかになるかというと、ページ 1 の読み込みは非常に高速で、ページ 1000 の読み込みはやや遅く、ページ 2000 の読み込みは非常に遅いということです。

于 2009-09-14T15:00:53.893 に答える