スキップしてメイン コンテンツに移動

[pymongo]ドキュメント数を取得(カウント)する最速の方法を検証。cursor.count()とcount_documents()ってどっちが早い?

はじめに

pymongoで検索結果のドキュメント数を知る方法に次の2通りのやり方がある。

  1. cursor型のcount()で件数を取得する方法
ret = collection.find(filter={検索条件}).count()
  1. コレクションのcount_documents()関数で取得する方法
ret = collection.count_documents(filter={検索条件})

どっちを使っても、条件に一致するドキュメント数が取得できます。
この記事では、上の2つの方法の内、どちらの方が高速に動くのかを検証してみます。

テストデータ

今回、実行時間の比較で使用するデータ(コレクション)は、次のような「ユーザID」「ユーザ名」と「点数」を持つ一般的な成績表データを使用します。なお、「点数」には1〜1000までのランダムな値を設定しておく。

id name score (ランダム値)
1 ユーザ1 100
2 ユーザ2 950
3 ユーザ3 550

Round1. 1000ドキュメント、filterなし(全件)

1回戦目は、簡単な条件で実行時間を測定してみたいと思います。以下の条件で実行時間を3回計測し、その平均値を比較しています。

  • ドキュメント数: 1000
  • 検索条件: なし

実行結果

この程度の件数であれは、どちらの関数を使用しても同じ時間で結果が返ってきます。

使用関数 実行時間
corsor.count 2.28ms
collection.count_documents 2.85ms

Round2. 10万ドキュメント、filterなし(全件)

2回戦目は、ドキュメント数を一気に増やして10万件で実行時間を比較してみます。

  • ドキュメント数: 10万
  • 検索条件: なし

実行結果

corsor.countの方が50倍近い速さで結果が返ってきています。この結果を見る限りだと、ドキュメント数の取得は、corsor.countを使った方がよさそうですね。

使用関数 実行時間
corsor.count 2.00ms
collection.count_documents 55.34ms

Round3. 10万ドキュメント、filterあり

次のは、検索条件を指定した時の実行時間を比較してみます。

  • ドキュメント数: 10万
  • 検索条件: 全体の「1%」のデータを抽出する検索条件を指定

※ この時の、検索条件を指定する列(score)のカーディナリティは**1%**です。

実行結果

今度は打って変わって、検索条件を指定した場合は、ほんの少しだけcount_documents()が早くなりました。ただ、誤差の範囲なので実行時間は同じと見てよいでしょう。

使用関数 実行時間
corsor.count 71.48ms
collection.count_documents 64.50ms

Round4. 100万ドキュメント、filter・skip・limitあり

ここまでの結論

ここまでの結果から、collection.find(filter={検索条件}).count()でカウントを取得する方が、総合的に早いと言う見解が得られました。

ここでの結果は、あくまで私の環境での実行結果から推測される私的な見解であり、実際は違うかもしれません。そのときはごめんなさい。

単純にコレクションのドキュメント数を知りたい場合

検索条件なしで、 単純にコレクション内の、ドキュメント数を知りたい場合 は、estimated_document_countを使うのが最速です。

pymongoのドキュメントにも、次のように書かれていす

 .. note:: For a fast count of the total documents in a collection see
    :meth:`estimated_document_count`.

実際に測定してみました。

  • 10万ドキュメント
使用関数 実行時間
corsor.count 2.09ms
collection.count_documents 61.10ms
collection.estimated_document_count 2.09ms
  • 1000万ドキュメント
使用関数 実行時間
corsor.count 8.97ms
collection.count_documents 5174.81ms
collection.estimated_document_count 2.05ms

上の結果の通り、estimated_document_count()関数を使った、カウントが最も早いです。

制限事項として、estimated_document_count()はセッションをサポートしていないので、セッションを指定したい時は使用できません。

スポンサーリンク
スポンサーリンク
スポンサーリンク

コメント

このブログの人気の投稿

axiosの使い方まとめ (GET/POST/例外処理)

axiosの使い方まとめ (GET/POST/例外処理)最近何かとよく使うJavaScriptでAJAX通信を行うaxiosについて、簡単に使い方をまとめました。GETリクエストをaxiosで送るまずはGETリクエストをaxiosで送る方法です。const res =await axios.get('/users') console.log(res.data)分割代入の記法を使うと、以下のようにも書けますconst{data}=await axios.get('/users') console.log(data)クエリパラメータ (URLパラメータ)を指定クエリパラメータを指定する方法は2つあります。1つ目は、axios.getに指定するURLに直接記述する方法です。axios.get('/user?id=123')2つめは、axios.getの第2引数に、オプション指定する方法です。axios.get('/user',{ params:{ id:123}})POSTリクエストをaxiosで送る次はPOSTリクエストをaxiosで送る方法です。JSON形式でPOSTするJSON形式でPOSTする場合は、axios.postの第2引数に、送信するデータをJavaScriptオブジェクトで指定します。const res =await axios.post('/user',{ id:123, name:'Yamada Tarou'})application/x-www-form-urlencoded形式でPOSTするapplication/x-www-form-urlencoded形式でPOSTする場合は、URLSearchParamsを使います。var params =newURLSearchParams() params.append('id',123) params.append('name','Yamada Tarou')const res =await axios.post('/user', params)axios でファイルをアップロードする画像などのファイルを、axiosでアッ…

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決する

[VB, C#] Windows 8, Window 10 で ImeModeが制御できない問題を解決するタイトルの通りですが、Windows 8 以降では Windows Form アプリケーションで、コントロールの ImeMode に Katakana や KatakanaHalf を設定しても、カタカナになってくれません。なぜ ImeMode が効かないのか?Windows 8 以降、IME Mode の切り替えは、ユーザー単位で切り替わるようになった為、アプリから IME Mode 制御が出来ないようになりました。
(IME をON にした場合、常に ひらがな モードになます)※ Windows 7までは、IME Modeの切り替えはアプリ単位で行われていた為、問題なくアプリから IME制御が行えました。対処方法Windows 8 以降、IMEの制御は、InputScope クラスの利用が推奨されています。
しかし、InputScope クラスは、WPF、Windows ストアアプリでしか使えない為、Windows Formアプリでは使用できません。
(Windows Form はもう使うな!という事でしょうか (涙) )結論としては、コントールパネルの設定で、IMEの制御をユーザ単位から アプリ単位に変更する事ができます。
これで、Windows Formアプリでも 従来通りIMEの制御を行う事が出来ます。おわりにこの方法だと、アプリをインストールする端末すべてに設定が必要となり、とっても面倒です。。。
しかし、今の所これしか方法がない状態です。
これからは Windows Formではなく、WPFや Windows ストアアプリで作れという事ですかね (^^;)

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]

MailKitの使い方! エンコーディング指定や添付ファイをメールで送信する方法[C#/VB Tips]MailKitを使ってメールを送るサンプルコードです。(C#)UTF8/iso-2022-jpのエンコーディング指定、GMail/YahooのSMTPサーバで送るなど、4つのサンプルコードでMailKitの使い方を紹介します。MailKitって何?2017年に.NET標準のSystem.Net.Mail.SmtpClientが廃止予定となり、Microsoftより今後はオープンソースライブラリである、MailKitに置き換えるとアナウンスがありました。既にSmtpClientは非推奨になっており、今後は廃止されていきます。現在、SmtpClientを使用したソースコードには、Visual StudioからMailKitを使うよう警告が出るようになっています。さっそく、MailKitを使ってメールを送信するサンプルコードを作っていきます。UTF8でメールを送信文字エンコーディングを、UTF8でメールを送信するサンプルコードです。
MailKitは、デフォルトの文字エンコーディングがUTF8なっている為、シンプルなコードでメールを送信する事ができます。var host ="<smtp server name>"; var port =25;// or 587using(var smtp =new MailKit.Net.Smtp.SmtpClient()){//SMTPサーバに接続する smtp.Connect(host, port, MailKit.Security.SecureSocketOptions.Auto);//認証が必要な場合は、以下のコメントを解除//smtp.Authenticate("<id>", "<password>");//送信するメールを作成する var mail =new MimeKit.MimeMessage(); var builder =new MimeKit.BodyBuilder(); mail.From.Add(new MimeKit.MailboxAddress("",&quo…