Skip to content

MySQL FULLTEXTが遅い理由

データ量が増えるとMySQL FULLTEXTは使い物にならないほど遅くなります。その原因と解決策を解説します。

何が問題なのか

ディスクI/Oがボトルネック

MySQL FULLTEXTはインデックスをディスク上のB-treeに保存しています。検索のたびに:

  1. ディスクからB-treeページを読み込み
  2. ポスティングリストをメモリに展開
  3. 結果のソート(大抵は外部ソート)

SSDを使っていても、このI/Oオーバーヘッドだけで100〜3000msかかります。

ポスティングリストが非圧縮

MySQLはポスティングリストを圧縮しません。「の」「を」のような頻出語で数百万件ヒットすると:

  • クエリごとに数MBのデータを読み込む
  • バッファプールを圧迫
  • 並列アクセスでキャッシュが効かなくなる

キャッシュ頼み

キャッシュの状態で性能が大きく変わります。110万件のWikipedia記事でのベンチマークでは、MySQL FULLTEXTのレイテンシはクエリとキャッシュ状態に応じて300ms〜2,566msの範囲でした。

本番環境では再起動・デプロイ・メモリ競合でキャッシュが効かない状況が頻発します。

並列アクセスで破綻

並列アクセスでMySQL FULLTEXTのスループットは急激に低下します:

ソリューション並列接続数QPS
MySQL FULLTEXT1-42-8
MygramDB1-42,634-11,766

MySQL FULLTEXTは低い並列数でも一桁台のQPSにとどまり、MygramDBは数千QPSを維持します。

解決策:MygramDB

MygramDBはアーキテクチャから見直すことでこれらの問題を解決しています。

すべてメモリ上

インデックスは全部RAM上。クエリ中のディスクアクセスはゼロです。

圧縮されたポスティングリスト

デルタエンコーディングとRoaringビットマップで、メモリ使用量を60〜80%削減。しかも検索は速くなります。

SIMD命令で高速化

ビットマップ演算にCPUのSIMD命令を活用し、スループットを最大化。

常に安定した性能

キャッシュの暖機運転は不要。常にサブミリ秒(0.08-0.42ms)で応答します。詳しい数値はベンチマークをご覧ください。

MySQL / MariaDBとリアルタイム同期

GTIDベースのbinlogレプリケーションで、MySQL 8.4/9.xまたはMariaDB 10.6+/11.xと自動同期。ETLパイプラインは不要、データの遅延もありません。

こんなサービスに最適

  • 高トラフィックなWebサービス — ECサイト、ニュースサイト、Q&Aサービスなど同時アクセスが多い環境
  • リアルタイム検索が必要 — ユーザーが即座に結果を期待する場面
  • FULLTEXTが100ms超 — 検索の遅さがUXを損なっている
  • 負荷時にタイムアウト — アクセス集中で検索が落ちる

試してみるならクイックスタートへ。詳しくはGitHubをご覧ください。