カミナリは、COUNT(*)クエリでDBをヒットせずに動作できますか?
私のアプリのデータベースは巨大であり、アイテムのカウントはアイテム自体を取得するよりもはるかに時間がかかり、パフォーマンスの問題につながります。
大規模なデータセットを使用する他のページネーションソリューションの提案も歓迎します。
カミナリは、COUNT(*)クエリでDBをヒットせずに動作できますか?
私のアプリのデータベースは巨大であり、アイテムのカウントはアイテム自体を取得するよりもはるかに時間がかかり、パフォーマンスの問題につながります。
大規模なデータセットを使用する他のページネーションソリューションの提案も歓迎します。
通常、ページ作成者はリンクを表示するためにレコードの総数を知る必要がありますが、レコードの総数を必要とせず、「前のページ」と「次のページ」のリンクだけが必要な場合もあります。このようなユースケースのために、Kaminariはwithout_count
、すべてのレコードの数をカウントせずにページング可能なコレクションを作成するモードを提供します。これは、非常に大きなデータセットを扱う場合に役立つことがあります。これは、RDBMSでは大きなテーブルを頼りにするのが遅くなる傾向があるためです。
.without_count
ページ付けされたオブジェクトに追加するだけです。
User.page(3).without_count
ビューファイルでは、フル機能のpaginate
ヘルパーの代わりに、次のような単純なヘルパーのみを使用できます。
<%= link_to_prev_page @users, 'Previous Page' %>
<%= link_to_next_page @users, 'Next Page' %>
さて、Kaminariまたはwill_paginateは、レンダリングされるtotal_pagesを決定するために、何らかの方法で合計をカウントする必要があります。これは避けられません。私の解決策は、データベースクエリを調べて、それを最適化することでした。それが進むべき道です。
(この回答は古くなっています。上記の回答を参照してください)
合計カウントが必要であるが、データベースにアクセスしたくない場合があります。適切なインデックスを使用している場合でも、COUNTクエリに数秒かかる場合があります。
そのため、親テーブルにカウンターキャッシュを追加し、トリガーで最新の状態に保ち、Relationオブジェクトのシングルトンをオーバーライドします。total_count
my_house = House.find(1)
paginated = my_house.cats.page(1)
def paginated.total_count
my_house.cats_count
end
...そして、カウントを必要とするすべてのものは、そのクエリを実行しなくても機能します。
これは珍しいことです。カウンターキャッシュの維持にはいくらかのコストがかかります。ページ付けされたデータでさらにリレーショナルな処理を行うと、奇妙な副作用が発生する可能性があります。シングルトンメソッドをオーバーライドすると、デバッグが悪夢になることがあります。ただし、慎重に使用し、十分に文書化することで、優れたパフォーマンスで必要な動作を得ることができます。