(Rails)何时使用ActiveRecord的.where和.select

时间:2015-12-02 03:48:16

标签: ruby-on-rails ruby-on-rails-3 activerecord

我的Rails应用中有一个名为User的模型,其中有一个属性name

假设我想查找Users与特定字符串匹配的所有name

在Rails控制台中,我可以这样做:

选项1

User.where("name LIKE 'string'")

这非常快。

选项2

User.select{|u| u.name == "string"}

这非常慢。它适用于一个小型数据库,但如果你有数十万用户,这似乎首先尝试将所有Users加载到内存中,然后在块中迭代它们。

这是否意味着选项2总是错误的? .select的正确用例是什么,何时优于.where

我在我的应用程序中编写了一堆代码,使用.select正常工作,但现在我尝试使用非常大的表,我看到我可能做错了。

1 个答案:

答案 0 :(得分:14)

选择:http://apidock.com/rails/ActiveRecord/QueryMethods/select

“这将从数据库为范围构建一个对象数组,将它们转换为数组并使用Array#select迭代它们。”

所以,它很慢,因为它从数据库中取出一切,逐个将它们转换为Ruby对象,然后运行你给它们的块。如果您有一个包含100,000行的数据库表,则表示实例化100,000个ruby对象并在其上运行块。 Ruby很慢,所以这很慢。

使用where基本上只是将一个SQL语句放在一起,让数据库处理它。数据库是快速的 - 如果速度是优先级,那么每当你可以推迟数据库时,你应该这样做。如果你有一个包含100,000行的数据库表,但只有10个匹配你的where查询,那么数据库将处理过滤,而Ruby只返回10行,因此只需要实例化10个Ruby对象,而不是100,000。

几乎总是,您需要使用where而不是select。那么,你什么时候可以选择?当你想根据一些相当难以翻译成SQL的ruby条件过滤相对少量的记录时,你会使用它(通常与where一起使用)。

示例:

User.where(account_cancelled: true).select do |u|
  # perform complex ruby logic on user 
  # that would be hard to do with plain SQL
  # (note, this will only act on the subset of 
  # users returned from the where clause)
end

因此,只要您合理地使用where而不是select,就应该这样做。

(还有第二次使用文档中提到的select:“修改查询的SELECT语句,以便只检索某些字段” - 但这不是你在问题中处理的用途)