【问题标题】:How to speed up a rails controller queries?如何加快 Rails 控制器查询?
【发布时间】:2020-01-09 05:39:19
【问题描述】:

我的应用程序即将陷入困境。有人可以帮我优化这个控制器代码以更快地运行吗?或者指出我正确的方向。 我正在尝试显示由 active 定义的客户列表为 true,而 active 为 false 的潜在客户列表。存档的客户是真实的。 谢谢你。

if current_user.manager?
  get_customers = Customer.where(:archived => false)
  @cc = get_customers.where(:active => true)
  @current_customers = @cc.where(:user_id => current_user.id)
  @count_current = @current_customers.count

  @pc = get_customers.where(:active => false)
  @potential_customers = @pc.where(:user_id => current_user.id)
  @count_potential = @potential_customers.count
end

这对提高速度有何影响?

型号

scope :not_archived, -> { where(:archived => false) }
  scope :current_customers, -> { where(:active => true).not_archived }
  scope :potential_customers, -> { where(:active => false).not_archived }
  scope :archived_customers, -> { where(:archived => true) }

控制器

 @current_customers = Customer.current_customers.includes(:contacts,:contracts)

查看

link_to "Current Clients #{@count_current.size}"

【问题讨论】:

  • 这取决于您到底想要什么,但现在他们的代码存在严重问题,您正在检索完整的客户列表,这意味着它将占用太多内存,而不是您查询它。第一个解决方案是使用分页,它会给你总数,并只返回有限的 10 条记录,但你将无法使用 :active => true!因此,请尝试考虑您必须在视图中显示的确切内容,并修改记录以仅获取包含、连接和其他选择特定查询的内容。另一种技术可以是检查数据库端创建了什么查询并使用解释查询。

标签: ruby-on-rails activerecord ruby-on-rails-5


【解决方案1】:

你可以找到帮助here

正如@Gabbar 指出的那样,我会补充一点,您的应用现在是eager-loading(与lazy-loading相反),这意味着您正在加载数据库中的数据比需要的多。我们需要做的是优化,但这完全取决于您的用例。

无论用例如何,您都可以做一些常见的事情来让事情变得更好: 您可以实现分页(有宝石,您也可以自己做)或无限滚动。在这种情况下,您将首先从 db 加载一定数量的记录,但一旦用户想要更多,他们将向下滚动或单击“下一步”按钮,您的操作将再次被调用,但页面中会增加number 表示获取下一组记录。

基于滚动的实现涉及到JS和view-height等,但是分页要简单得多。

宝石:

kaminari gem

infinite-pages

使用includes

您必须做的另一件事是,如果您的记录相关,请在查询中使用包含。使用 include 很棘手,但在节省时间方面非常有帮助。与您的代码多次往返数据库不同,它将一次性从数据库中获取相关的所需记录。与从 RAM 中获取相比,从数据库中获取需要花费大量时间。

@users = User.all.includes(:comments) #comments for all users brought along with users but saved in RAM for future access.
@comments = @users.map(&:comments) # no need to go to db again, just RAM.

在模型中使用scopes

在模型中创建范围也有帮助。在您的情况下,您应该创建这样的范围:

  scope :archived_customers, -> { where('archived IS false') }
  scope :potential_customers, -> { where('active IS false') }

  **OR**

  scope :archived_customers, -> { where(:archived => false) }
  scope :potential_customers, -> { where(:active => false) }

【讨论】:

  • 关于includes:在开发过程中对我有帮助的是“子弹”宝石,它(大部分时间正确)指出包含缺失或多余的地方。
  • 如何提高速度?模型范围:not_archived,-> { where(:archived => false) } 范围:current_customers,-> { where(:active => true).not_archived } 范围:potential_customers,-> { where(:active => false) .not_archived } 范围 :archived_customers, -> { where(:archived => true) } @current_customers = Customer.current_customers.includes(:contacts,:contracts) 查看 link_to "Current Clients #{@count_current.size}"
【解决方案2】:

在单个查询中加载所有可用记录的成本可能非常高。此外,用户可能只对最近的几条记录(即博客中的最​​新帖子)感兴趣,并且不想等待所有记录加载和呈现。

有几种方法可以解决这个问题

Load More 的示例#1 实现

Infinite Scrolling 的示例#2 实现

pagination 的示例#3 实现

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 2020-05-14
    • 2011-02-18
    • 1970-01-01
    • 2012-07-20
    • 1970-01-01
    相关资源
    最近更新 更多