回答:
あなたはそれを読むべきです、それはまだ有効です。
必要に応じて、使用する機能を調整します。
基本的に:
すでにすべてのエントリをロードしている場合、たとえばUser.all
、次のlength
dbクエリを回避するために使用する必要があります
何もロードしていない場合count
は、dbでカウントクエリを作成するために使用します
これらの考慮事項に煩わされたくない場合size
は、適応する使用
size
により、size
(どちらを呼び出すかを決定した後で)を呼び出すときに、それらを呼び出すことができます。
Comment.create(post_id: post.id)
、post.comments.size
最新の状態にpost.comments.count
はなりませんが、最新の状態になります。だから注意してください。
company.devices.build(:name => "device1"); company.devices.build(:name => "device2")
それから、company.devices.size
と.length
あなたが建てられましたが、保存していないオブジェクトの数が含まれますが、.count
データベースからのみのカウントを報告します。
他の答えが述べるように:
count
SQL COUNT
クエリを実行しますlength
結果の配列の長さを計算しますsize
過剰なクエリを回避するために、2つのうち最も適切なものを選択しようとしますしかし、もう1つあります。全体的size
にcount
/ と違う振る舞いをするケースに気づき、length
見過ごすほど珍しいので共有したいと思いました。
あなたが使用している場合:counter_cache
にhas_many
協会、size
直接カウントキャッシュされて使用し、すべての余分なクエリをすることはありません。
class Image < ActiveRecord::Base
belongs_to :product, counter_cache: true
end
class Product < ActiveRecord::Base
has_many :images
end
> product = Product.first # query, load product into memory
> product.images.size # no query, reads the :images_count column
> product.images.count # query, SQL COUNT
> product.images.length # query, loads images into memory
_count
(counter_cache: true
関連付けのディレクティブなしで)列があったとしても、この動作がトリガーされていました。これがで修正されていgithub.com/rails/rails/commit/e0cb21f5f7
時々size
「間違ったものを選択」し、ハッシュ(これは何をcount
するか)
その場合は、ハッシュではなく整数length
を取得するために使用します。
count
。length
。size
...送信に解決 Select count(*)...
クエリをDBます。データが必要ない場合の方法ですが、カウントのみです。
例:新しいメッセージの数、ページのみが表示される場合の合計要素など。
必要なデータ、つまり必要に応じてクエリを読み込み、それをカウントします。データを使用している場合の方法。
例:完全に読み込まれたテーブルの概要、表示されたデータのタイトルなど
データがロードされているかどうか(つまり、すでにレールにあるかどうか)をチェックし、ロードされている場合はそれをカウントし、そうでない場合はcountを呼び出します。(さらに、他のエントリですでに言及されている落とし穴)。
def size
loaded? ? @records.length : count(:all)
end
どうしたの?
正しい順序で実行しないと、DBを2回ヒットする可能性があります(たとえば、レンダリングされたテーブルの上にあるテーブルの要素数をレンダリングすると、実質的に2つの呼び出しがDBに送信されます)。
次の戦略はすべて、データベースを呼び出してCOUNT(*)
クエリを実行します。
Model.count
Model.all.size
records = Model.all
records.count
以下は、データベースからすべてのレコードをRubyにロードし、コレクションのサイズをカウントするため、効率的ではありません。
records = Model.all
records.size
モデルに関連付けがあり、所属するオブジェクトの数(など@customer.orders.size
)を知りたい場合は、データベースクエリ(ディスク読み取り)を回避できます。カウンタキャッシュを使用すると、Railsはキャッシュ値を最新の状態に保ち、size
メソッドに応答してその値を返します。
Model.all.size
をModel.all.count
生成しcount
ます。の本当の利点はsize
、関連付けが既に読み込まれている場合、カウントクエリが生成されないことです。Rails 3以前Model.all
では、リレーションではないので、すべてのレコードがすでに読み込まれています。この回答は古くなっている可能性があるため、削除することをお勧めします。
サイズ関数の使用をお勧めします。
class Customer < ActiveRecord::Base
has_many :customer_activities
end
class CustomerActivity < ActiveRecord::Base
belongs_to :customer, counter_cache: true
end
これらの2つのモデルについて考えます。顧客には多くの顧客活動があります。
has_manyアソシエーションで:counter_cacheを使用する場合、サイズはキャッシュされたカウントを直接使用し、追加のクエリをまったく作成しません。
1つの例を考えてみます。私のデータベースでは、1人の顧客が20,000の顧客活動を持っているので、その顧客の顧客活動のレコード数を、カウント、長さ、サイズの各方法でカウントしようとしています。これらのメソッドすべてのベンチマークレポートを以下に示します。
user system total real
Count: 0.000000 0.000000 0.000000 ( 0.006105)
Size: 0.010000 0.000000 0.010000 ( 0.003797)
Length: 0.030000 0.000000 0.030000 ( 0.026481)
そのため、:counter_cache Sizeを使用するのが、レコード数を計算するための最良のオプションであることがわかりました。
size
、とにかく状況に適応し、その後、どのような必要性のためにそこにあるlength
とcount
まったく?