2016-09-26 9 views
0

をフィルタリングされたときに私の質問のより一般的なバージョンが既に尋ねたビークました:Count vs len on a Django QuerySetCountはいくつかの結果が

私の場合は、しかし、少し異なっています。

messages = Message.objects.filter(foo=bar) 

error_message_countother_message_countを取得するには、優れている:それはこのような何かで始まりますか?

error_message_count = len(message for message in messages if message.is_error) 
other_message_count = len(messages) - error_message_count 

か:

error_message_count = messages.filter(is_error = True).count() 
other_message_count = messages.count() - error_message_count 

かさえ:

error_message_count = messages.filter(is_error = True).count() 
other_message_count = messages.filter(is_error = False).count() 

私は最初の解決策は一つだけのクエリに帰着し、2つで他と思われます。しかし、おそらくDjangoやDBMSは、2番目の2つのうちの1つをより効率的にするでしょうか?

私は答えとして「プロフィール」を受け入れますが、これらの解決策のいずれかがベストプラクティスと考えられるかどうかは疑問です。

+0

これらのリクエストされたメッセージを後で使用しているのですか、それとも2つの数字だけを取得したいのですか?元のフィルタリングされたリスト(数十、千)に含まれるメッセージの数はいくつですか?リストの予想されるエラー率はいくらですか? – serg

+0

良い質問ですが、私は実際に答えを確信していません。数字はページの上部にあるステータスアイコンです。ユーザーはメッセージをクリックしてメッセージを表示したり無視したりすることができます。私はメッセージの数についてはわかりませんが、数十を超える数があれば驚くでしょう(私の場合、この質問はパフォーマンスよりもスタイルに関するものですが、誰かが非常に異なるアプリケーションはいつか)。私はまた、エラーになる割合についても分かりません。ユーザはそれが非常に小さいことを望むだろうが、実際には第三者のデータの品質に依存する。 –

答えて

2

私が知っている限り、すべてのオブジェクトを取得し、ブール値を1つずつチェックすると、メモリを使用するpythonを使用して行うため、良い方法ではありません。 一方、 'count'はデータベースで実行され、1つのブール値をチェックするためにすべての行を取得する必要はありません。したがって、私は良い方法が中間のものだと思います。

error_message_count = messages.filter(is_error = True).count() 
other_message_count = messages.count() - error_message_count 

また、あなたが「メッセージ」を定義したとき、それはクエリセットですが、あなたは遅延評価を使用することが必要になるまで、それはDBに実行されません。ですから、そのクエリーセットのforループを使用すると、そのクエリーセットが直接実行されます。しかし、必要なブール値に別のフィルタを追加すると、データベースクエリのみが更新されます。そのため、パフォーマンスが向上します。これらの間で決定する

+0

私は3つの方法のいずれかが2つのクエリになることを確信しています。'messages'オブジェクトが作成されたときにクエリが実行され、そのオブジェクトの存続期間中に結果がキャッシュされると思います。 (ジェネレータ関数が各反復のためにクエリを再実行した場合、Djangoには驚いて深く失望します!)しかし、DBサーバーがコードをより効率的にフィルタリングするように調整されていることは間違いありません。クライアント。ありがとう。 –

+1

反復ごとにクエリを実行しません。しかし、主なことは、あなたがデータベースでそれを行うことができれば、そこでそれを行うことです。方法がない場合は、すべての情報を取得して反復することを検討してください。したがって、count関数を使用すると、データベース内のcountが使用され、非常に高速に実行されます。良い一日を持ってください:) –

1

error_message_count = len(message for message in messages if message.is_error) 
other_message_count = len(messages) - error_message_count 

か:

error_message_count = messages.filter(is_error = True).count() 
other_message_count = messages.count() - error_message_count 

messagesテーブルの大きさは何だ、すなわち考慮する必要があるいくつかの重要な要因は、あなたがis_errorにインデックスを持っていますがありますどのくらい+ve/-veと一致しますか。残念ながら、profile-itは本当にあなたに鮮明な画像を与えます。テーブルサイズが小さい場合(例:数千のエントリの場合は問題ありません)それが数百万のエントリのオーダーであれば、プロフィールではっきりとした画像を得るのはかなり簡単です。

+0

うーん、はい、is_error列をインデックス化する必要があります。念押し有難う。 ☺ –

関連する問題