Rails 7: リレーションの結果が空になる計算でクエリ送信を回避する(翻訳)
従来は、count
などの計算で、矛盾するリレーションを渡してもSQLクエリが発行されていました。ここで言う"矛盾する"リレーションとは、以下のように空の配列などを渡すことを指します。
User.where(id: []).count
このようなリレーションでデータベースを呼び出すのは無意味です。
改修前
Rails 7より前は、count
、sum
、average
、minimum
、maximum
で使われるリレーションが矛盾していてもデータベースが呼び出されました。
=> Product.where(title: []).count
Product Count (4.7ms) SELECT COUNT(*) FROM "products" WHERE 1=0
=> 0
=> Product.where(title: []).sum(:price)
Product Sum (17.5ms) SELECT SUM("products"."price") FROM "products" WHERE 1=0
=> 0
=> Product.where(title: []).average(:price)
Product Average (3.5ms) SELECT AVG("products"."price") FROM "products" WHERE 1=0
=> nil
=> Product.where(title: []).minimum(:id)
Product Minimum (5.0ms) SELECT MIN("products"."id") FROM "products" WHERE 1=0
=> nil
=> Product.where(title: []).maximum(:id)
Product Minimum (5.0ms) SELECT MAX("products"."id") FROM "products" WHERE 1=0
=> nil
ご覧のとおり、矛盾するものを渡してもクエリが送信されています。
改修後
改修後は、データベースへのクエリ送信を回避するようになります。
=> Product.where(title: []).count
=> 0
=> Product.where(title: []).sum(:price)
=> 0
=> Product.where(title: []).average(:price)
=> nil
=> Product.where(title: []).minimum(:id)
=> nil
=> Product.where(title: []).maximum(:id)
=> nil
詳しくは#45030を参照してください。
概要
元サイトの許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。
参考: 週刊Railsウォッチ20220516 矛盾するリレーション上の計算でクエリを発行しないようにする
#45030は、現時点ではmainブランチにのみ含まれており、7-0-stableブランチには含まれていません。