querysetの存在確認にexists()とcount()はどちらの方が早い?

今回はDjangoのquerysetの存在確認にexists()とcount()はどちらの方が早いのかについて調査した結果について書きたいと思います。

先にネタバレしますが、count()よりもexists()の方がパフォーマンスが良いのでquerysetの存在確認のためには素直にexists()を使用すると良いでしょう。
exists()を使用した場合はquerysetの件数が増えてもほぼパフォーマンスが変わらないです。

動作環境としてはDjangoのバージョンは3.0.1を使用しており、Pythonのバージョンは3.7.3を使用しております。



querysetの存在確認にexists()とcount()はどちらの方が早い?

querysetのexists()とcount()どちらがパフォーマンス的に良いのか調べるために次のソースを用意しました。

count_test()はcount()を使って1万回querysetの存在確認してそのタイムを計る関数です。
対して、exists_test()はexists()を使って1万回querysetの存在確認してそのタイムを計る関数です。

次のBookモデルを使ってタイムを計測します。

初期条件として、Bookオブジェクトが一個だけある場合を考えてみます。

手始めにcount_test()を三回実行してみます。

count_test()を三回実行した結果はこちらです。

count_test()の実行時間は約2秒ちょっとという結果になりました。

一方、exists_test()を三回実行してみます。

exists_test()を三回実行した結果は次の通りです。

exists_test()は2秒を切るという結果になりました。
現時点で結果だけ見るならばcount()よりもexists()の方がパフォーマンスが良いということになります。

querysetの件数を増やしてみる

では、先ほどの実験ではquerysetの総数が1個だけでしたが、querysetの件数を増やしてみた場合はどうなるのでしょうか。

querysetの件数を1件ではなく100万件に増やして実験してみます。

まず100万件に増やしたquerysetに対してcount_test()を三回実行した結果はこちらです。

実行時間がめちゃくちゃ増えていますね。
count_test()を一回実行するために40秒をオーバーしています。

一方、exists_test()を実行した場合はどうでしょうか。

exists_test()を三回実行した結果はこちらです。

exists_test()はquerysetの件数が増えてもパフォーマンスが良いままです。
というよりquerysetの件数を100万件にしても、querysetの件数が1件の時とパフォーマンスがほぼ変わらないように見えます。

querysetのexists()は最初の一件のみで評価している

querysetのexists()を使ってもquerysetの件数が1件の時と100万件の時でパフォーマンスにほとんど変化が見られないのは内部のロジックのおかげです。

Djangoの公式ドキュメントによると、querysetのexists()は最初の1件のみを評価しております。
querysetの総数が1件だけだろうが100万件あろうが最初の1件のみを見るので実行時間はほぼ変わらないようですね。

querysetの存在確認に関してはcount()よりもコードとして見た目も良くquerysetの数が増えたときにパフォーマンスがほぼ変わらないexists()を使用すると良いでしょう。

終わりに

今回はDjangoのquerysetの存在確認にexists()とcount()はどちらの方が早いのかについて調査した結果について書きました。

最後までお読みいただきありがとうございます。
よろしければブログやTwitterでのシェアをお願いいたします。
コメントもお待ちしております。
誤植や勘違いなどございましたらコメント欄にて教えていただけると幸いです。






Django

Posted by ちこ