変数にActiveRecordクエリを割り当てることは、クエリの結果を返すことに注意することが重要です。このようなもの:
@categories = Category.where(public: true)
公開されているすべてのカテゴリの配列を返しません。代わりに、クエリを定義するRelation
を返します。データベースへのクエリは、実際のレコードを返す必要があるリレーション内のメソッドを呼び出すと実行されます。たとえば、each
、load
、count
です。
言い換えれば、関係でblank?
を呼び出すと、Railsはそれを知る必要があります。関係は空の配列を返しません。それははるかに高速で問い合わせるので
SELECT COUNT(*) FROM categories WHERE public = 1
その唯一のことは、あなたが任意の一致するレコードがあるかどうかを知る必要がある場合、すべてのレコードをフェッチ:そのためのRailsのようなクエリを実行します。
一方、@categories[0]
の動作は異なります。ここでは、すべてのレコードをロードして、すべてのマッチングカテゴリを保持する配列を持ち、その配列の最初のレコードを返す必要があります。
この時点で、両方のバージョンはデータベースへのクエリでのみ実行されました。しかし、あなたの次のステップは、もしあればレコードを繰り返し処理することだと思います。最初のバージョン(blank?
)を使用した場合、オブジェクトはロードされず、カウントされたにすぎません。したがって、Railsは実際のレコードを照会する必要があり、結果として2番目の照会となります。 2番目のサンプル([0]
)にはすでにレコードがロードされているため、秒単位のクエリは必要ありません。
あなたの考えでは何が最善の方法でしょうか、そのカウントクエリのために私はタイムアウトを得たので、それは私がチェックした理由です – django
レコードがあるかどうかを確認した後に結果セットを反復するとすれば、 'unless @ categories.length.zero? '。 'length'は常にレコードを最初にロードするので、' count'は決して実行しません。レコードがロードされていない場合、 'size'は' count'に戻ります。タイムアウトに関しては、どのようにクエリがどのように見えるのですか?データベーステーブルに適切なインデックスが適切に配置されていますか? – spickermann
これは私のhttps://explain.depesz.com/s/cHQyを分析し、これは11980ms – django