我有一张桌子,里面有大约500,000名用户。当我使用我的Rails 3.0控制台并键入
时User.first
我立刻得到了结果。但是当我输入
User.first(1)
需要几秒钟。可能导致这种情况的原因是什么?
注意:
之间发生了同样的事情User.last
和
User.last(1)
答案 0 :(得分: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
作为参数调用number
时,它会加载所有用户的数据库然后离开用户数组中只有number
个元素。
first
的{{3}}看起来像这样
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
所以很好。但在recent Rails code中它是:
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
参数是Integer
ActiveRecord是否加载了所有数据,将其转换为数组并调用Array的first
方法,该方法具有以下行为:older version like Rails 3.0.7