pluck と map はどちらを使うべきなのか?
Userモデルの全レコードを取得して、idの配列を作成した時で試してみる
require 'bebnchmark'
Benchmark.bm 10 do |r|
  r.report "pluck" do
    User.all.pluck(:id)
  end
  r.report "map" do
    User.all.map(&:id)
  end
end
結果としてはこんな感じ
         user     system      total        real
pluck  0.003826   0.000972   0.004798 (  0.013440)
map    0.022315   0.002486   0.024801 (  0.070383)
mapの方がだいぶ長い。。。SQL的には何が違うんだろ
# pluck 
SELECT `users`.`id` FROM `games`
# map
SELECT `users`.* FROM `games`
なるほど。
pluckは指定したカラムのみをSQLで取ってきている。
また、pluck必要なフィールドだけを読み込むことで、メモリの使用量も削減できるとの事で
これが圧倒的に早い理由らしい
→ pluckでメモリを大幅に節約する(翻訳)
mapの方が早いパターン
上の例だけみると常にpluckの方が早そうだけど、mapの方が早いパターンはあるのか?
調べてみた。
require 'bebnchmark'
users = User.all
Benchmark.bm 10 do |r|
  r.report "pluck" do
    2000.times { users.pluck(:id) }
  end
  r.report "map" do
    2000.times { users.map(&:id) }
  end
end
        user    system      total        real
pluck 4.725170   0.867798   5.592968 (  6.395219)
map   1.070974   0.006997   1.077971 (  1.079586)
この場合、mapの方が断然早い!
繰り返し処理を実行する場合、pluckは毎回SQLを発行してしまう。(この場合だと2000回発行してしまってます)
一方、mapは一回しか発行していない。
まとめ
- SQLの段階で必要なカラムだけを取ってこれるので、対象のレコードを配列に整形する場合などは
pluckが早い - 一方、繰り返し処理のなかで
pluckを使うと毎回SQLを発行してしまうので危険。その場合はmapを使った方が断然早い