2

我有一张桌子,里面有大约 500,000 个用户。当我使用我的 Rails 3.0 控制台并输入

User.first

我立即得到结果。但是当我输入

User.first(1)

这需要几秒钟。这可能是什么原因造成的?

注意:同样的事情发生在

User.last

User.last(1)
4

1 回答 1

4

我在 Erb (Rails 3.0.7) 中打开日志显示并产生以下结果

1.8.7 :004 > User.first
  User Load (4.3ms)  SELECT `users`.* FROM `users` LIMIT 1
 => #<User id: 1, email: "user@project.ru">
1.8.7 :005 > User.first(1)
  User Load (0.4ms)  SELECT `users`.* FROM `users`
 => #<User id: 1, email: "user@project.ru">
1.8.7 :008 > User.first(2)
  User Load (0.4ms)  SELECT `users`.* FROM `users`
 => [#<User id: 1, email: "user@project.ru", #<User id: 2, email: "user@gmail.com">]

所以我们可以看到,当您first不带参数调用时,它按预期工作,但是当我们first使用numberas 参数调用时,它会加载 DB 的所有用户,然后只number在 users 数组中保留元素。

最近的 Rails 代码first看起来像这样

def first(*args)
  if args.any?
    if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
      limit(*args).to_a
    else
      apply_finder_options(args.first).first
    end
  else
    find_first
  end
end

所以还是可以的。但在Rails 3.0.7 等旧版本中,它是:

def first(*args)
  if args.any?
    if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
      to_a.first(*args)
    else
      apply_finder_options(args.first).first
    end
  else
    find_first
  end
end

因此,您可以看到first参数是否为IntegerActiveRecord 加载所有数据,将其转换为数组并调用 Array 的first方法,该方法具有以下行为:http ://www.ruby-doc.org/core-1.9.3/Array.html#method -我先来

于 2013-01-23T06:27:00.493 回答