6

我有一个will_paginate的当前实现,它使用paginate_by_sql方法来构建要分页的集合。我们有一个针对total_entries的自定义查询,该查询非常复杂,会给我们的数据库带来很大的负担。因此,我们希望完全从分页中删除 total_entries。

换句话说,我们只需要一个“下一个 - 上一个”按钮,而不是典型的分页显示“上一个 [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 回答