'pluck'每次重新获取缓存关联?

时间:2017-04-21 10:29:08

标签: ruby-on-rails activerecord

我知道由于对象构建的成本,pluck比使用selectmapping object更高效。 但我发现pluck不使用ActiveRecord_Associations_CollectionProxy的缓存。例如:

irb(main):001:0> u = User.take
irb(main):002:0> puts Benchmark.measure { u.rides.map(&:id) }
  Ride Load (1.3ms)  SELECT "rides".* FROM "rides" WHERE "rides"."user_id" = $1  ORDER BY "rides"."created_at" DESC  [["user_id", 1]]
  0.040000   0.020000   0.060000 (  0.072337)
irb(main):003:0> puts Benchmark.measure { u.rides.map(&:id) }  # once again, fetching data from the cache
  0.000000   0.000000   0.000000 (  0.000103)
irb(main):004:0> puts Benchmark.measure { u.rides.pluck(&:id) }
  (1.6ms)  SELECT "rides"."id" FROM "rides" WHERE "rides"."user_id" = $1  ORDER BY "rides"."created_at" DESC  [["user_id", 1]]
  0.010000   0.010000   0.020000 (  0.020381)
irb(main):005:0> puts Benchmark.measure { u.rides.pluck(&:id) }  # once again, refetch data from database
  (1.5ms)  SELECT "rides"."id" FROM "rides" WHERE "rides"."user_id" = $1  ORDER BY "rides"."created_at" DESC  [["user_id", 1]]
  0.010000   0.010000   0.020000 (  0.020810)

这是正常的吗?以这种方式使用mappingselect而不是pluck更好吗?

BTW,我正在使用Rails-4。

更新

我不确定这是一个错误,它似乎是由Rails 5修复的。rails/rails#25976

1 个答案:

答案 0 :(得分:0)

pluck每次都会转到DB。如果您不想在内存中加载所有匹配的记录但只想要特定列的值,那么它很有用。

您要为其获取所选列值的记录可能已经加载到内存中。这就是你的例子所显示的内容。第一次调用u.rides会加载该用户的所有记录。对该集合的后续调用只会在内存对象中用于不同的操作。

我建议您阅读http://blog.arkency.com/2013/12/rails4-preloading/一次。