Skip to content
← ブログに戻る

50,000 通のメールをミリ秒で検索:MailVault のローカルインデックスの仕組み

7分で読めます

MailVault に単語を入力すると、キーを押し終える前に新しい順の一致結果が画面に出ます。メールボックスが本当に大きくてもこれが成り立つのかを確かめるため、50,000 通の保管庫を作って検索時間を測りました。最も遅かったクエリでも 14 ミリ秒でした。

この記事では、実際の数値、何を測って何を測っていないか、そしてその裏にある技術、つまり保管庫の中にある小さくてシンプルな SQL データベースを紹介します。

テストの内容

実際のメールと同じマルチパートの HTML とプレーンテキストの形式で、1 通あたり約 3.3 KB のメッセージを 50,000 通生成しました。3 つのフォルダー(受信トレイ、アーカイブ、送信済み。それぞれおよそ 3 分の 1)に振り分け、既知の単語を既知の割合で仕込んでいます。「invoice」はメッセージの 5%、「budget」は 8%、「meeting」は 6% で、日本語やアクセント付きの単語も加えて、英語以外の検索も試しました。すべてのメッセージは、リリースビルドの MailVault の実際の MIME パーサーと実際のインデックス処理を通しています。

使ったマシンは、メモリ 16 GB の Apple M4 Mac mini です。アイドル状態ではなく、テスト中も他のビルドが動いていたので、この時間は負荷のかかったコンピューターでの結果と考えてください。各クエリは 6 回実行しました。修正を入れた作業用ビルドで 3 回、マージ後のコードで 3 回です。下の数値はその実行全体の範囲で、各時間には検索と、一覧に表示される結果行の組み立てが含まれます。

結果

50,000 messages · Apple M4 · warm cache · 6 runs each

query                    matches   rows shown   time
invoice                  ~2,500    500          7.1 – 7.5 ms
budget meeting           246       246          13.4 – 14.1 ms
update 4999              15        15           13.5 – 14.0 ms
会議 (Japanese)         1,529     500          4.3 – 4.6 ms
last 7 days, no words    1,008     500          1.0 ms

first index build        11 s      (10.9 – 11.9 s)
index size on disk       225 MB
status check             5 ms

この表から読み取れることが 2 つあります。1 つ目は、時間が一致件数に比例しないことです。15 件の一致のほうが 2,500 件よりも長くかかりました。時間を左右するのはクエリの形(2 語のフレーズは 1 語より手間がかかる)で、返ってくるメールの量ではありません。2 つ目は、一覧に表示されるのは新しい順で最大 500 件までで、それを超える場合はその旨が表示されることです。そのため、何通一致しても結果の描画にかかる作業量には上限があります。

50,000 通のメッセージを保管した MailVault の保管庫で、invoice という語を検索した結果です。検索ボックスの下に、すべてのフォルダーで保存済みの一致約 2,500 件のうち新しい 500 件を表示していると示され、その下にメッセージ行の一覧が続きます。
アプリでの同じ種類の検索です。50,000 通のメッセージを保管した保管庫で「invoice」を検索しました。一覧には保存済みの一致約 2,500 件のうち新しい 500 件が表示され、そのことも明記されています。先頭の数行はこのウィンドウを共有するデモ用メールボックスのもので、保管庫のフォルダー名はベンチマークとは異なり Projects、Correspondence、Clients です。
Search time per query on 50,000 messages, in milliseconds Five bars: last 7 days with no words 1.0 ms, Japanese query 4.5 ms, invoice 7.4 ms, budget meeting 14.0 ms, update 4999 14.0 ms. Every bar ends before the 16.7 ms mark, which is one screen refresh at 60 Hz. 0 5 10 15 20 milliseconds, search plus building the result rows last 7 days, no words 1 ms 会議 (Japanese) 4.5 ms invoice 7.4 ms budget meeting 14 ms update 4999 14 ms one 60 Hz screen refresh: 16.7 ms
50,000 通のメッセージに対するクエリごとの検索時間。どのバーも、60 Hz の次の画面更新より前に終わっています。

一度だけかかるコストはインデックスの構築で、50,000 通でおよそ 11 秒、毎秒約 4,000 通のペースで、ディスクは 225 MB です。構築はバックグラウンドで行われ、実行中も MailVault を使い続けられます。その後は、新しいメッセージと変更されたメッセージだけがインデックスされます。

MailVault の設定、ストレージタブにある検索インデックスのカードです。50,000 / 50,000 件がインデックス済みで約 270 MB と表示され、メッセージ本文、添付ファイルのテキスト、画像内のテキストのスイッチが並んでいます。
設定、ストレージ、検索インデックスの構築が完了した状態です。50,000 通中 50,000 通がインデックス済みで、ディスク上の容量は約 270 MB です。アプリ内の別の実行なので、上のベンチマーク表の 225 MB とは容量が異なります。

1 ms と 7 ms はどんな感覚か

ミリ秒は想像しにくいので、ものさしを用意しました。60 Hz のディスプレイは 16.7 ms ごとに再描画され、ここでの最も遅い検索でも 1 回の再描画の間に終わりました。ユーザビリティ研究では 1993 年から同じ 3 つの限界が使われています。0.1 秒未満なら瞬時に感じ、1 秒までなら思考の流れが途切れず、10 秒になると注意が離れてしまいます。14 ミリ秒は「瞬時」の限界の約 7 分の 1 です。1 ms の日付フィルターは、その 100 分の 1 です。

How long is a millisecond? Search times on a logarithmic time scale A logarithmic ruler from 1 millisecond to 100 seconds. MailVault search sits between 1 and 14 milliseconds, close to one screen refresh at 16.7 milliseconds and far below the 100 millisecond point at which a response feels instant. The old file-by-file search projected to 88 seconds on a 20,000-message folder. 1 ms 10 ms 100 ms 1 s 10 s 100 s MailVault search on 50,000 messages: 1 to 14 ms one screen refresh 16.7 ms at 60 Hz feels instant under 100 ms flow of thought up to 1 s attention lost after 10 s old search 88 s (projected)
時間軸は対数目盛りで、1 ミリ秒から 100 秒までです。目盛りが 1 つ進むごとに 10 倍になります。応答時間の目安: Jakob Nielsen。88 s の点は、ファイルを 1 つずつ調べる従来の検索を 20,000 通のフォルダーで実行した場合の推定値です。

サーバーのメール、アーカイブ、バックアップを 1 回の検索で

MailVault のクエリの検索結果。下部の凡例で、サーバーのみ、保管庫の中、唯一のコピー、バックアップドライブ上の印を説明している
検索結果にはすべて、メッセージの所在が表示されます。サーバーのみ、保管庫の中、唯一のコピー、バックアップドライブ上のいずれかです。

MailVault は 3 種類のメールを並べて保管します。サーバーから同期したメッセージ、自分でアーカイブしたメッセージ、バックアップから復元したメッセージです。どれも同じ保管庫の中のファイルになるので、すべて同じインデックスに入ります。テストでは、メールは受信トレイ、アーカイブ、送信済みの各フォルダーにあり、1 つのクエリで全体を検索しました。メッセージの出どころによって、見つかる速さは変わりません。

サーバーにしかなく、まだダウンロードしていないメールは保管庫に入っていないため、ローカルのインデックスからは見えません。そのため MailVault はサーバーにも問い合わせ、サーバーが応答する間は、インデックス済みのローカルの結果が先に表示されます。この部分はプロバイダー次第なので、数値は公表していません。Premium では、サーバーのメールボックスを 1 つではなく最大 5 つまで同時に検索できます。

外付けのバックアップドライブは、2 つ目のコールドコピーです。検索は作業用の保管庫に対して実行され、バックアップドライブにもコピーがある場合は、結果にその印が付きます。

技術: とても速く、とてもシンプルな SQL データベース

検索サーバーもクラウドサービスもありません。インデックスは保管庫の中にある 1 つの SQLite ファイルで、SQLite はおそらく世界で最も広く使われているデータベースです。MailVault は SQLite の全文検索エンジン FTS5 を trigram トークナイザーとともに使います。すべての単語が、重なり合う 3 文字の断片として保存されます。だから「voic」と入力すれば「invoice」が見つかり、ワイルドカードも単語全体の一致も要りません。アクセント記号は正規化されるので、「reunion」で「Réunion」も見つかります。単語の間にスペースを置かない日本語や中国語は、そのために作られた別のテーブルで処理されます。

速さは、3 つの素朴な判断から生まれています。

  • 検索でメッセージファイルを開くことはありません。一覧に必要な情報(差出人、件名、日付、フォルダー、フラグ)は、インデックスの行にそのまま保存されています。50,000 通のテストでは、結果を組み立てる間にメールパーサーが呼ばれた回数はゼロでした。
  • 1 つのファイル、1 つのプロセス。インデックスは MailVault のバックグラウンドヘルパーが所有し、一度開いたらそのまま待機させておきます。起動するものも、ネットワークで送るものもありません。
  • 正本はあくまでディスク上のメールです。インデックスは派生データです。万一壊れても、MailVault は保存済みのメッセージから作り直し、メッセージ自体には一切触れません。

オフラインで動作し、何もコンピューターの外に出ません。

添付ファイルと画像 (Premium)

無料の検索では、差出人、件名、メッセージ本文が対象です。Premium では、添付ファイルの中のテキストも同じインデックス、同じ検索ボックスで検索できます。

  • 添付ファイルのテキスト。PDF、Word、Excel、PowerPoint のファイルを読み取ってテキストをインデックスに加えるので、契約番号で検索すれば、その番号が PDF の中にあるメッセージが見つかります。
  • macOS での画像とスキャンのテキスト。MailVault は Mac 上の Apple の Vision フレームワークで、写真、スクリーンショット、スキャンしたページの文字を認識し、インデックスに加えます。認識はデバイス上で実行されます。Windows と Linux にはこの工程はありません。

添付ファイルの中だけに存在するヒットには、クリップの印が付くので、本文が目立たないメールが表示された理由がわかります。今回のテストでは添付ファイルからの抽出時間は測っていません。抽出時間はファイル次第で、検索時ではなく、添付ファイルごとに 1 回、バックグラウンドで実行されるためです。

他のメールクライアントは検索をどう説明しているか

他のメールアプリはベンチマークしていません。以下のどのアプリも、50,000 通での検索時間は公表していません。そのため、これはストップウォッチの比較ではなく、設計の比較です。

  • Apple Mail: Apple の説明によると、Spotlight の最初のインデックス作成はデータ量によって数時間、場合によっては数日かかることがあり、Mail にはインデックス作成が未完了であることを知らせる通知が表示されることがあります。
  • Windows 版 Outlook は Windows Search のインデックスを使います。Microsoft の案内では、インデックス作成が終わるまで結果が不完全になることがあること、インデックスされるのはローカルにキャッシュされたメールだけであること、検索結果が多すぎると古い項目が表示されないことがあることが示されています。
  • Thunderbird は独自のデータベースにグローバルインデックスを保持しています。バグトラッカーには、大きなメールボックスでインデックス作成が遅くなる問題についての長期にわたる報告があり、36,000 通に数日かかったというユーザーもいます。これらは古いハードウェアでのユーザー報告であり、今回のテストとは直接比較できません。

私たちの設計は、一般的なものとは逆です。自分で保存したコピーにインデックスを作り、それを小さな 1 つのファイルにまとめ、クエリの経路を短く保つことで、答えがミリ秒単位で返ってきます。

このテストでわからないこと

メールボックスは人工的なものです。実際のメールはもっと大きく雑多なので、本文が長い場合はインデックスも大きくなりますが、クエリが調べるのはインデックスであって、ファイルではありません。時間はウォームキャッシュでの値で、再起動後の最初の検索ではディスクからより多く読み込みます。テストの対象は件名、差出人、本文で、添付ファイルのテキストは含まれず、実行したのは 1 台のマシンです。

測定は自分で再現できます。ベンチマークは MailVault のソースツリーにある、無視指定の Rust テスト search_index_bench_50k_real_parser で、上に挙げた数値をすべて出力します。

6 年前のメールを、ミリ秒で見つけましょう。

MailVault はアーカイブのそばにプライベートな検索インデックスを持つので、50,000 通でも 500 通と同じように簡単に検索できます。無料でお使いいただけます。添付ファイルと画像の検索は Premium に含まれます。

出典: Apple サポート、Spotlight のインデックス作成Microsoft サポート、Outlook の検索の問題Mozilla Bugzilla 585429。ベンチマークは 2026年9月21日に測定しました。