MySQL FULLTEXTが遅い理由
データ量が増えるとMySQL FULLTEXTは使い物にならないほど遅くなります。その原因と解決策を解説します。
何が問題なのか
ディスクI/Oがボトルネック
MySQL FULLTEXTはインデックスをディスク上のB-treeに保存しています。検索のたびに:
- ディスクからB-treeページを読み込み
- ポスティングリストをメモリに展開
- 結果のソート(大抵は外部ソート)
SSDを使っていても、このI/Oオーバーヘッドだけで100〜3000msかかります。
ポスティングリストが非圧縮
MySQLはポスティングリストを圧縮しません。「の」「を」のような頻出語で数百万件ヒットすると:
- クエリごとに数MBのデータを読み込む
- バッファプールを圧迫
- 並列アクセスでキャッシュが効かなくなる
キャッシュ頼み
キャッシュの状態で性能が大きく変わります。110万件のWikipedia記事でのベンチマークでは、MySQL FULLTEXTのレイテンシはクエリとキャッシュ状態に応じて300ms〜2,566msの範囲でした。
本番環境では再起動・デプロイ・メモリ競合でキャッシュが効かない状況が頻発します。
並列アクセスで破綻
並列アクセスでMySQL FULLTEXTのスループットは急激に低下します:
| ソリューション | 並列接続数 | QPS |
|---|---|---|
| MySQL FULLTEXT | 1-4 | 2-8 |
| MygramDB | 1-4 | 2,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を損なっている
- 負荷時にタイムアウト — アクセス集中で検索が落ちる