2009-09-14 4 views
5

を向上させるためにtotal_entries。 total_entriesのカスタムクエリは非常に複雑で、DBに大きな負荷を与えます。したがって、ページ分割からtotal_entriesをすべて削除したいと考えています。なしwill_paginateを使用して:私はページ分割されるコレクションを構築するための<strong>paginate_by_sql</strong>メソッドを使用しています<strong>will_paginate</strong>の現在の実装を持って長いクエリ

つまり、 'previous 1 [2] 3 4 5 next'のページ区切り表示の代わりに、 'next-previous'ボタンだけが好きなだけです。しかし、私たちはいくつかのことを知る必要があります。

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

を表示されている場合、これはあなたが提供しない 場合は、行をカウントするためのクエリが 自動的に生成されますdocs

から表示されませんでした。この で生成されたSQLで の問題が発生した場合は、 アプリケーションで を手動で実行するとよいでしょう。

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

  • total_entriesを削除し、それが半ページネーションをナビゲートするだけで次/前のボタンを使用して
  • 利用可能なすべてのページ番号を表示する必要がないと一度にデータベース
  • 表示50のレコードにあまり負荷を引き起こしているので、カウント
  • のみに応じて次のボタンと前のボタンを表示

誰でも同様の問題で働いたり、解像度の考えを持っていますか?

答えて

13

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数値の行を返します。

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

+0

ありがとうございました。私はハックして、私が思いつくことができるものを見るつもりです。私はいくつかの長いSQLカスタムクエリを扱うことになっていますが、私はそれらをソリューションに取り入れ、パフォーマンスがどのようになるかを知ることができるはずです。ありがとう! – mwilliams

+0

お返事ありがとうございます。ニースとシンプルな、私はそのような単純な解決策を超えて見えました。私の実装の大部分は既に整っており、はるかに優れているようです。私は次の/前のボタンに問題がありますが、私はすぐにそれを叩き出してしまいます。再度、感謝します! – mwilliams

関連する問題

 関連する問題