Rail的default_scope对性能的影响

时间:2015-04-09 02:38:47

标签: ruby-on-rails performance postgresql activerecord default-scope

可以 default_scope 用于不按ID 对Rails应用程序显着减慢记录订单吗?

例如,我有一个使用PostgreSQL的Rails(目前是3.1)应用程序,其中几乎每个Model都有一个default_scope排序记录的名称:

default_scope order('users.name')

现在因为default_scope的订单记录在name而不是ID 我担心我可能会遭受重大的性能损失正常查询运行时。 例如:

User.find(5563401)

@User.where('created_at = ?', 2.weeks.ago)

User.some_scope_sorted_best_by_id.all

在上面的示例中,我的模型上default_scopename可能会导致性能下降?我应该关注影响应用程序性能的default_scope吗?

1 个答案:

答案 0 :(得分:4)

你的问题忽略了这一点。默认作用域本身只是几微秒的Ruby执行,导致order by子句被添加到发送到PostgreSQL的每个SQL语句中。

所以你的问题实际上是在询问无序查询和有序查询之间的性能差异。

Postgresql documentation is pretty explicit。对无索引字段的有序查询比无序字段慢得多,因为(毫不奇怪),PostgreSQL必须在返回结果之前对结果进行排序,首先创建临时表或索引以包含结果。这可能很容易成为查询时间的4倍,可能更多。

如果您引入索引只是为了实现快速排序,那么您仍然需要为每次插入和更新维护索引。除非它是主要索引,否则排序访问仍然涉及随机搜索,实际上可能比创建临时表更慢。这也在Postgres文档中讨论过。

简而言之,永远不要将一个order子句添加到不需要它的SQL查询中(除非您喜欢等待​​数据库)。

注意:我怀疑一个简单的find()将附加订单,因为它必须返回一个结果。您可以通过启动rails console,发出查找并观察生成的SQL滚动来快速验证这一点。但是,whereall肯定会被订购,因此肯定会比所需的慢。