所以,我想知道下面哪个更有效。最好的答案应该是,我以后怎么才能自己搞清楚。
这两个查询是:
# id integer
# created_at datetime
# collection_id integer
# updated_at datetime
class Post < ActiveRecord::Base
belongs_to :collection
end
Post.where(:collection_id => collection_id).order(:updated_at).last
和
Post.where(:collection_id => collection_id).order("updated_at DESC").first
两部分问题:
1)哪个语句更有效?(除非我打错了,它们应该是相等的)
2)我怎么能自己回答这个问题呢?
我假设没有索引。我还想知道答案是否会根据查询的by collect_id部分的结果集的预期大小而变化。
至少在Rails 3.1中,您的两个查询实际上将在数据库上运行相同的查询。Rails足够聪明,知道在查询上调用.last
应该只是颠倒顺序并将其限制为单个请求。因此,下面这行实际上只是将ORDER BY updated_at DESC LIMIT 1
添加到查询的末尾。换句话说,这一行不是返回数据库中的所有记录,为每个记录创建ActiveRecord对象,然后然后返回最后一个记录,这样效率会低得多。
Post.where(:collection_id => collection_id).order(:updated_at).last
如果您观察控制台,您将看到(1)实际正在执行哪些查询(或查询),以及(2)执行所花费的时间。这将是跟踪效率的基本方法。
在生产环境中,也有像NewRelic RPM这样的工具,它会给你警告/分析执行查询的速度/时间。我认为免费版本会做效率分析,但只保留应用程序运行前30分钟的记录。
一般来说(但不严格来说),发送的查询数量越少越好,部分原因是它涉及到Rails和DB之间更少的往返。
如果你想要一些免费的,也许更可重复的东西,那么你可以添加一些性能测试,你可以一遍又一遍地运行查询,每次运行计时,并确保查询/控制器动作的运行时间小于你选择的某个基准,或者多次执行的平均时间低于某个阈值。
此方法还可以用于监视应用程序中最常执行的操作,如果它们花费的时间比预期的长,则会失败。该测试将只覆盖模拟环境,当然,它可以用作关键操作是否完全偏离预期性能的一般指示。