🐘
あるカラムが最大値のレコードをパフォーマンスよく取得する
概要
現場でカラムが最大値のレコードを1件取得するという処理を書いたときに、
レビュワーの方からパフォーマンス面での指摘があったので、備忘録として残しておきます。
環境
ruby '3.1.2'
'rails', '~> 7.0.8'
修正前のコード
修正前のコードがこちらです。
class Commnent < ActiveRecord::Base
def self.article_type_first
where(type: "Article").max_by(&:id)
end
end
問題点
こちらのコードだと、まずは type が "Article" のものを全件取得します。
SELECT "comments".* FROM "comments" WHERE "comments"."type" = 'Article';
それに対して Ruby の max_by
を使用して、id
が最大値のレコードを1件取得します。
つまり、欲しいコードは1件だけなのに、全件取得するという無駄なことをやってしまうわけです。
修正後のコード
修正後のコードがこちらです。
class Comment < ApplicationRecord
def self.article_type_first
where(type: "Article").order(:id).last
end
end
改善点
上記のコードの場合、以下の SQL が発行されます。
SELECT "comments".* FROM "comments" WHERE "comments"."type" = 'Article' ORDER BY "comments"."id" DESC LIMIT 1;
つまり、 ORDER_BY 句によって並び替えた後、最初のレコードを見つけ、即座にそのレコードのみを返します。
まとめ
レコードを取得するときは ActiveRecord を使って最適化されたクエリを発行するようにしましょう。
Discussion