gpt4 book ai didi

mysql - Rails + MySQL - 从具有特定格式的 3 个表加载数据(非常慢 "has_many"关系)

转载 作者:太空宇宙 更新时间:2023-11-03 16:00:08 25 4
gpt4 key购买 nike

我有这样的表格结构:

用户

id | name
1 | John
2 | Peter
3 | Claire

服务

id | name
1 | home
2 | garden
3 | music

用户服务

id | user_id | services_id
1 | 1 | 3
2 | 2 | 3
3 | 1 | 2

型号:用户.rb

class User < ActiveRecord::Base
has_many :user_services, dependent: :destroy
has_many :services, through: :user_services
end

user_service.rb

class UserService < ActiveRecord::Base
belongs_to :user
belongs_to :service
validates_uniqueness_of :service_id, scope: :user_id
end

服务.rb

class Service < ActiveRecord::Base
has_many :user_services
has_many :users, through: :user_services
end

这就是我所做的( Controller ):

def do_search
@results = search_users
@users_a = []
@users_b = []

@results[:users].each do |result|
is_user_b = 0
result.user_services.each do |service|
if service.service_id == 28
@users_a << "a string..."
is_user_b = 1
break
end
end
if is_user_b == 0
@users_b << "string B"
end
end
render "results_users"
end

def search_users
@users = User.within(distance, origin: city).where('gender = ?', 0).order("distance ASC")
end

在 View 中:

<% @results[:users].each do |result| %>
<li data-services="<% result.services.each do |service| %><%= service.name %>,<% end %>">
<div><%= result.facility_name %></div>
<ul class='service-icons cf'>
<% result.services.each do |service| %>
<li class='service-icon'>
<span class="streamline" aria-hidden="true" data-icon="<%= raw service.icon %>" title="<%= service.label %>"></span>
</li>
<% end %>
</ul>
</li>
<% end %>

问题:此流程非常慢 - SQL 查询非常快(0.4 秒),但是处理这 3 个循环(1 个在 Controller 中,2 个在 View 中)非常慢,这导致显示结果持续大约 < strong>60 秒。

这让我很惊讶,因为我有几乎相同的模型,但是有cars (cars, services, car_services), 几乎与 users 相同数量的属性 (cars), 在 cars 中是 600k 记录, 在 users 90K 仅需 2 秒即可完成。我花了一整天试图找出原因,但仍然不明白这怎么可能。

谁能帮帮我,为什么遍历 has_many 关联要花这么多时间? (如果我评论所有 3 个循环,页面将在 2 秒内加载)

提前感谢您的宝贵时间。

最佳答案

实际上 Active Record 在处理大型数据集方面真的很糟糕。

然而,您应该做的第一件事是通过预先加载相关记录来避免代码在这些循环中执行的大量 n+1 查询,这些记录将在迭代中访问

 User.includes(:user_services, :services).within(...).where(...)

与每次循环迭代发出单独的 +1 查询相比,一次获取所有记录要快得多。

您还应该考虑为用户及其服务引入分页或一些其他用户发起的额外抓取(例如“显示更多”)。无论如何,人类将难以处理大量数据。

如果此优化不充分并且一次获取所有数据的要求是不可协商的,那么请使用原始 SQL。为每一行实例化一个 ActiveRecord Objectgraph 的影响是巨大的。通过这种方式,我们已经能够将我们的账单报告从几分钟优化到几秒钟。

我还推荐使用“rack-mini-profiler”gem 来分析性能问题。

关于mysql - Rails + MySQL - 从具有特定格式的 3 个表加载数据(非常慢 "has_many"关系),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27216956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com