我对ActiveRecord比较新,我和Sinatra一起使用。目前,我正在建立小规模的网站。我没有遇到任何问题花了太长时间,但我想知道如何最好地优化搜索,所以我的网站是可扩展的。
这是我一直想知道的事情。 ActiveRecord是否将分解为多个函数的查询视为一个函数?
# Single
BlogPost.last(5)
# Broken Down
BlogPost.all.limit(5)
这是一个概念性问题:ActiveRecord如何运行搜索?添加更多功能会降低搜索效率吗?当您将查询分解为多个函数BlogPost.where(publish: true)
时 - 假设where(publish: true)
返回50个结果,limit
将其限制为5个。它是否首先找到所有五十publish: true
然后在五点之后切断所有内容,或者它是否足够智能以在找到前五个后停止搜索?
答案 0 :(得分:2)
你的预感是正确的。将ActiveRecord查询链接起来是一种很好的做法。
说你的BlogPost表有一百万行。
然后说BlogPost.all
会很慢,但说BlogPost.all.limit(1)
会很快。
all和limit都是ActiveRecord的一部分。返回值响应Array方法但不是数组。这有一些例外。例如,find_by / find返回模型实例,但您可以将它们作为链中的最后一个查询方法。 pluck返回一个普通的ruby数组。
BlogPost.all[1]
与BlogPost.all
一样慢,因为[ ]是一个数组方法,而不是ActiveRecord。
当您将ActiveRecord方法链接在一起时,在将方法转换为数组或尝试读取某些数据之前,不会执行查询。
所以query = BlogPost.all.order(id: :desc).reorder(id: :asc).limit(1)
实际上没有从数据库加载任何数据。另请阅读preloading data),它可以解决慢N+1次查询问题。
如果您随后说query.to_a
,query.reduce
等,那么Arel(构建ActiveRecord的内容),最终确定查询并执行它。
您可以致电<query>.to_sql
查看基础查询:
class Foo < ActiveRecord::Base
end
Foo.all.to_sql
#=> "SELECT \"foos\".* FROM \"foos\""
Foo.all.limit(1).to_sql
#=> "SELECT \"foos\".* FROM \"foos\" LIMIT 1"