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のデータを読み込む
  • バッファプールを圧迫
  • 並列アクセスでキャッシュが効かなくなる

キャッシュ頼み

キャッシュの状態で性能が2〜3倍変わります:

状態クエリ時間
キャッシュなし2,980ms
キャッシュあり908ms

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

並列アクセスで破綻

負荷がかかるとMySQL FULLTEXTは壊滅します:

並列数成功率平均応答
1100%908ms
1010%4,641ms
1000%タイムアウト

たった10並列で9割のクエリが失敗します。

解決策:MygramDB

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

すべてメモリ上

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

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

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

SIMD命令で高速化

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

常に安定した性能

キャッシュの暖機運転は不要。いつでも80ms以下で応答します。

並列数成功率平均応答
1100%32ms
10100%35ms
100100%190ms

MySQLとリアルタイム同期

GTIDベースのbinlogレプリケーションでMySQLと自動同期。ETLパイプラインは不要、データの遅延もありません。

こんなサービスに最適

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

始め方

bash
docker run -d --name mygramdb \
  -p 11016:11016 \
  -e MYSQL_HOST=your-mysql-host \
  -e MYSQL_USER=repl_user \
  -e MYSQL_PASSWORD=your_password \
  -e MYSQL_DATABASE=mydb \
  -e TABLE_NAME=articles \
  ghcr.io/libraz/mygram-db:latest

詳しくはGitHubをご覧ください。

Released under the MIT License.