【发布时间】:2022-01-13 00:35:35
【问题描述】:
- Rails v5.2.4.3
- Ruby v2.3.3
我们有一个 Workspace 表和一个 WorkspaceGroup 表,这两个表之间的多对多关系通过一个名为 WorkspaceGroupAssociation 的连接表(工作区就像我们的域模型中的项目)。所以一个项目可以属于很多组,一个组可以有很多项目。
我们有一些团队有数千个项目,在我们的可观察性工具中,我们最近注意到以下旧代码非常慢(注意以下代码是该方法的简化版本):
class WorkspaceGroup < ApplicationRecord
def add_workspaces(workspace_ids)
self.workspace_ids |= workspace_ids
end
end
我们有一个小组已经有大约 5,000 个工作区,添加这些新的工作区 ID 需要超过 2 分钟。
我们最初的方法是将self.workspace_ids |= workspace_ids 更改为self.workspace_ids += workspace_ids,但这在性能方面根本没有改变。然后我们尝试了以下方法,效果很好:
def add_workspaces(workspace_ids)
existing_workspaces = self.workspaces
workspaces_to_add = Workspace.where(id: workspace_ids) - existing_workspaces
workspaces_to_add.each do |workspace|
self.workspaces << workspace
end
end
上述代码的作者说性能提升是因为我们没有在新代码中实例化 5,000 个 Workspace 模型的新实例,而是在旧代码中。
我很好奇为什么旧代码是这样,而新代码却不是。为什么self.workspace_ids += 会导致实例化数千个新的 ActiveRecord 实例,而self.workspaces << 不会?
【问题讨论】:
标签: ruby-on-rails rails-activerecord