🐘

あるカラムが最大値のレコードをパフォーマンスよく取得する

2024/01/12に公開

概要

現場でカラムが最大値のレコードを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