2017-02-19 13 views
1

result.blankの比較を見つけることはほとんどありませんか?と結果[0]ので、今日私はこれらの2つの方法で1つのクエリをチェックしていた今日。ここで余分なカウントの呼び出しを引き起こすブランクチェック

コード、変数はActiveRecordの結果である@categories、

はこのブランクチェックは

if @categories.blank? 
end 

AS count_all SELECT COUNT(*)のような1つの余分デシベルコールを呼び出すしかし、ここで余分なことをされた結果クエリがそこに表示されていません。

if @categories[0] 
end 

これには論理がありますか?私はそれを見つけることができませんでした

答えて

0

変数にActiveRecordクエリを割り当てることは、クエリの結果を返すことに注意することが重要です。このようなもの:

@categories = Category.where(public: true) 

公開されているすべてのカテゴリの配列を返しません。代わりに、クエリを定義するRelationを返します。データベースへのクエリは、実際のレコードを返す必要があるリレーション内のメソッドを呼び出すと実行されます。たとえば、eachloadcountです。

言い換えれば、関係でblank?を呼び出すと、Railsはそれを知る必要があります。関係は空の配列を返しません。それははるかに高速で問い合わせるので

SELECT COUNT(*) FROM categories WHERE public = 1 

その唯一のことは、あなたが任意の一致するレコードがあるかどうかを知る必要がある場合、すべてのレコードをフェッチ:そのためのRailsのようなクエリを実行します。

一方、@categories[0]の動作は異なります。ここでは、すべてのレコードをロードして、すべてのマッチングカテゴリを保持する配列を持ち、その配列の最初のレコードを返す必要があります。

この時点で、両方のバージョンはデータベースへのクエリでのみ実行されました。しかし、あなたの次のステップは、もしあればレコードを繰り返し処理することだと思います。最初のバージョン(blank?)を使用した場合、オブジェクトはロードされず、カウントされたにすぎません。したがって、Railsは実際のレコードを照会する必要があり、結果として2番目の照会となります。 2番目のサンプル([0])にはすでにレコードがロードされているため、秒単位のクエリは必要ありません。

+0

あなたの考えでは何が最善の方法でしょうか、そのカウントクエリのために私はタイムアウトを得たので、それは私がチェックした理由です – django

+0

レコードがあるかどうかを確認した後に結果セットを反復するとすれば、 'unless @ categories.length.zero? '。 'length'は常にレコードを最初にロードするので、' count'は決して実行しません。レコードがロードされていない場合、 'size'は' count'に戻ります。タイムアウトに関しては、どのようにクエリがどのように見えるのですか?データベーステーブルに適切なインデックスが適切に配置されていますか? – spickermann

+0

これは私のhttps://explain.depesz.com/s/cHQyを分析し、これは11980ms – django

関連する問題