【Rails】ActiveRecord の select メソッドでインスタンスを軽量化しよう
こんにちは!
ラブグラフエンジニアのひろです。
今回は、インスタンスを軽量化して負荷を減らすことができる select
メソッドについてです。
いくつか注意点もあるので、ぜひ最後まで読んでいってください。
はじめに
大量のデータを処理しなければならないとき、 ActiveRecord の select
メソッドは負荷軽減のための有効な手段となり得ます。
この記事では、 select
メソッドの基本的な使い方から、似たメソッドである pluck
との違い、使用する際の注意点まで解説します。
select メソッドとは
select
メソッドは、 ActiveRecord のクエリメソッドの一つで、データベースから取得するカラムを限定することができます。
Rails ガイド:特定のフィールドだけを取り出す
通常のクエリでは、モデルに対応するテーブルの全カラムが取得されますが、 .select
を使うことで必要なカラムだけを取得することができます。
# すべての User を取得
users = User.all
# User Load (2.5ms) SELECT `users`.* FROM `users`
# =>
# [#<User:0x0000ffff32862bfs
# id: 1,
# name: "hiro",
# email: "a@test.com"
# age: nil,
# birthday: nil,
# avator: nil,
# created_at: Mon, 19 Aug 2024 12:00:00.387980000 JST +09:00,
# updated_at: Mon, 19 Aug 2024 12:00:00.387980000 JST +09:00>,
# ...
# User モデルから name と email カラムだけを取得する
users = User.select(:name, :email)
# User Load (1.2ms) SELECT `users`.`name`, `users`.`email` FROM `users`
# =>
# [#<User:0x0000ffff32862bfs id: nil, name: "hiro", email: "a@test.com">,
# ...
select メソッドでできること
select
メソッドを使うことで、次のようなメリットがあります。
-
SQLクエリのパフォーマンス向上
- 取得するデータ量が少なくなるため、SQLクエリの実行時間が短縮される
-
メモリ使用量の削減
- 軽量化されたインスタンスを使用することで、メモリ使用量が減る
-
インスタンスメソッドが使える
- 軽量化しつつもインスタンスの形を保っているため、メソッドを呼び出すことができる
pluck との違い
ActiveRecord の pluck
メソッドも特定のカラムを取得するために使用されますが、 pluck
は配列を返し、 select
は ActiveRecord の Relation オブジェクトを返すという違いがあります。
# User モデルから name, email カラムだけを配列として取得する
name_and_emails = User.pluck(:name, :email)
# SELECT `users`.`name`, `users`.`email` FROM `users`
# =>
# [["hiro", "a@test.com"],
# ...
必要なデータがカラムの値だけなのか、それともインスタンスの状態で欲しいのか、適切に使い分けましょう。
select メソッドを使用する際の注意点
select
で指定しなかったカラムにアクセスしようとすると、例外が発生します。
user = User.select(:name, :email).first
user.age # age カラムが存在していたとしても、 select に含めていないので NoMethodError が発生する
その場で処理するだけなら良いですが、そのインスタンスを各所で使い回している場合、
未来の自分が NoMethodError に遭遇することが十分考えられるため、コメントで明示するか、変数名で特定のカラムしか取得していないことを表現するのが良いでしょう。
まとめ
このように select
メソッドを使うことで、インスタンスの形を保ったまま、パフォーマンスの向上を目指すことができます。
大量のデータを扱う際には、インスタンスのすべての情報が必要かどうか考えてみて、 select
メソッドの活用を検討してみてください。
Discussion