我知道由于对象构建的成本,pluck
比使用select
或mapping 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)
这是正常的吗?以这种方式使用mapping
或select
而不是pluck
更好吗?
BTW,我正在使用Rails-4。
我不确定这是一个错误,它似乎是由Rails 5修复的。rails/rails#25976
答案 0 :(得分:0)
pluck
每次都会转到DB。如果您不想在内存中加载所有匹配的记录但只想要特定列的值,那么它很有用。
您要为其获取所选列值的记录可能已经加载到内存中。这就是你的例子所显示的内容。第一次调用u.rides
会加载该用户的所有记录。对该集合的后续调用只会在内存对象中用于不同的操作。