我想进行查询,但查询速度很慢,我有五个这样的模型:
class Mya < ActiveRecord::Base
has_many :mybs
end
class Myd < ActiveRecord::Base
belongs_to :myc
end
class Myc < ActiveRecord::Base
belongs_to :myb
has_many :myds
has_many :myes
end
class Myd < ActiveRecord::Base
belongs_to :myc
end
class Mye < ActiveRecord::Base
belongs_to :myc
end
,我将一些测试数据插入mysql :(种子)
mya=Mya.create!(title: 'first test')
i=0
10.times{
i=i+1
myb=Myb.create!(title: "my_#{i}")
5000.times{
myc=Myc.create!(mya_id: mya.id, myb_id: myb.id)
4.times {
myd=Myd.create!(mya_id: mya.id, myb_id: myb.id, myc_id: myc.id)
mye=Mye.create!(mya_id: mya.id, myb_id: myb.id, myc_id: myc.id)
}
}
}
在我的控制器中,我喜欢这样:
def index
@ms = Mya.first.to_json(:include => [{
mybs: {
:include => {
:mycs => {
:include => [:myds, :myes]
}
}
}
}
])
render json: @ms
end
非常慢,帮助我,谢谢。抱歉我的英语。
答案 0 :(得分:5)
您正在运行双嵌套n + 1查询。那意味着你
Mya
(1个查询)
Myb
的{{1}}(1个查询)
Mya
个每个 Myc
(10个查询)
Myb
的所有(4)Myc
(10 * 5000个查询)Myc
的所有(4)Myd
(10 * 5000个查询)这意味着您正在运行1 + 1 + 10 +(10 * 5,000)+(10 * 5,000)= 100,012个查询。由于每个查询都有一些开销,因为它需要向数据库发送数据和从数据库接收数据,因此控制器操作变得非常慢。
您可以通过告诉ActiveRecord在第一个查询中使用includes
方法包含嵌套的Myc
s Myb
和Myc
来阻止这种情况发生。这样,您将只执行一个大型查询,ActiveRecord将只与该数据库进行一次通信。
Myd