pluckとmap の違いを調査する


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を使った方が断然早い