2017-05-03 43 views
0

在性能和逻辑方面,Rails的Active Record查询中“排序”“过滤器”(Desc或Asc)的位置是否重要?可交换性和活动记录范围的顺序

例如是1的SAM以下范围作为范围2

SCOPE 1

scope :default_stream, -> { order(deal_end_date: :asc) } # this is the "sorting query" 
scope :scope_1, 
     lambda { default_stream.where('deal_start_date <= ? AND deal_end_date >= ?', Time.zone.now, Time.zone.now).where(is_cool: true) } 

SCOPE 2

scope :scope_2, 
     lambda { Deal.all.where('deal_start_date <= ? AND deal_end_date >= ?', Time.zone.now, Time.zone.now).where(is_cool: true).order(deal_end_date: :asc) } 

我应该先用“排序查询“那么其他过滤器(scope1)还是相反(scope2)?

不知道是否有冲击,但让我说,交易的数量是非常重要的(> 100000)

回答

1

没关系。直到您尝试阅读结果时,您的范围才被实际评估。 orderwhere子句可以以任意顺序附加到关系中,因为它们被放置在最终SQL查询中的相同位置。

如有疑问,请尝试两种方法,并在您的示波器上调用.to_sql。您会发现scope1.to_sqlscope2.to_sql完全相同。

给出一个简单的模型Post,你会发现,Post.order(:name).where(active: true)Post.where(active: true).order(:name)产品相同 SQL:

select * from posts where active = true order by name 

无论是orderwhere发生的 “第一”,这是不可能的。只有一个SQL查询生成,并且它的所有各种子句(where,order,limit,offset等)到达需要生成语法上有效查询的位置。

+0

所以先把非排序查询(其中('deal _..... Time.zone.now).where(is_cool:true))不会更快?我认为,因为它会输出有限/更少的行数,所以排序查询(order(deal_end_date::asc))作为第二步将比排序整个数据库行更快...你说的实际上是(bar)'和'.where(foo).order(bar)的结果,它是通过活动记录自动为此优化的? – Mathieu

+0

@Mathieu这根本不是那种工作方式。 ''会做**完全相同的事情**,它们将产生*相同* SQL和*相同*记录。排序/过滤由数据库完成,而不是由Ruby完成。'order'或'where'发生“第一次”; Rails将它们全部(不管你以什么样的顺序调用它们)并将它们变成**一个** SQL查询 – meagar

+0

好吧,我明白了,将会检查.to_sql的疑问:)。非常感谢我指出了正确的方向 – Mathieu