インデックス問題の解決方法
一部のクエリの実行速度が期待値に達しない場合、オプティマイザーがクエリを実行するために間違ったインデックスを選択している可能性があります。
オプティマイザーが予期しないインデックスを選択する理由は複数あります。
- 古い統計: オプティマイザーは統計に基づいてクエリ コストを見積もります。統計が古い場合、オプティマイザーは最適ではない選択を行う可能性があります。
- 統計の不一致: 統計が最新であっても、データ分布を正確に反映していない可能性があり、コストの見積もりが不正確になる可能性があります。
- コスト計算が正しくありません: クエリ構造やデータ分散が複雑なため、オプティマイザーがインデックスの使用コストを誤って計算する場合があります。
- 不適切なエンジン選択: 場合によっては、オプティマイザーがクエリに最適ではないstorageエンジンを選択することがあります。
- 関数プッシュダウンの制限: 特定の関数または操作がstorageエンジンにプッシュダウンされない可能性があり、クエリのパフォーマンスに影響する可能性があります。
統計の健康
まず統計のテーブルの健全性状態表示し、次にさまざまなヘルス状態に応じてこの問題を解決できます。
健康状態が低い
ヘルス状態が低いということは、TiDB がANALYZE
のステートメントを長時間実行していないことを意味します。3 ANALYZE
のコマンドを実行すると、統計を更新できます。更新後もオプティマイザーが間違ったインデックスを使用する場合は、次のセクションを参照してください。
ほぼ100%の健康状態
ほぼ 100% のヘルス状態は、 ANALYZE
ステートメントが完了したばかりか、少し前に完了したことを示しています。この場合、間違ったインデックスの問題は、TiDB の行数の推定ロジックに関連している可能性があります。
同等性クエリの場合、原因はカウントミニマムスケッチである可能性があります。Count-Min Sketch が原因であるかどうかを確認し、対応する解決策を実行できます。
上記の原因が問題に当てはまらない場合は、 USE_INDEX
またはuse index
オプティマイザーヒントを使用してインデックスを強制的に選択できます (詳細については使用インデックス参照)。また、 SQL プラン管理使用して非侵入的な方法でクエリの動作を変更することもできます。
その他の状況
前述の状況以外にも、データの更新によってすべてのインデックスが適用できなくなった場合にも、間違ったインデックスの問題が発生する可能性があります。このような場合は、条件とデータ分布を分析して、新しいインデックスによってクエリが高速化されるかどうかを確認する必要があります。高速化できる場合は、 ADD INDEX
コマンドを実行して新しいインデックスを追加できます。
統計の不一致
データ分布が大きく偏っている場合、統計は実際のデータを正確に反映しない可能性があります。このような場合は、 ANALYZE TABLE
ステートメントのオプションを構成してみてください。統計の精度が向上し、インデックスとの一致が向上する可能性があります。
たとえば、 customer_id
列にインデックスがあるorders
テーブルがあり、注文の 50% 以上が同じcustomer_id
共有しているとします。この場合、統計はデータ分布を適切に表さず、クエリのパフォーマンスに影響する可能性があります。
費用情報
実行コストの詳細情報を表示するには、 FORMAT=verbose
オプションを使用してEXPLAIN
およびEXPLAIN ANALYZE
ステートメントを実行します。この情報によると、異なる実行パス間のコストの違いを確認できます。
エンジンの選択
デフォルトでは、TiDB はコスト見積もりに基づいてテーブル アクセスに TiKV またはTiFlash を選択します。エンジン分離を適用することで、同じクエリに対して異なるエンジンを試すことができます。
詳細についてはエンジン分離参照してください。
関数プッシュダウン
クエリのパフォーマンスを向上させるために、TiDB は特定の関数をTiKV またはTiFlashstorageエンジンにプッシュダウンして実行できます。ただし、一部の関数はプッシュダウンをサポートしていないため、使用可能な実行プランが制限され、クエリのパフォーマンスに影響する可能性があります。
プッシュダウンをサポートする式については、 TiKV はプッシュダウン計算をサポートしましたとTiFlashはプッシュダウン計算をサポート参照してください。
特定の式のプッシュダウンを無効にすることもできます。詳細については、 最適化ルールと式プッシュダウンのブロックリスト参照してください。