インデックス問題の解決方法
一部のクエリの実行速度が期待値に達しない場合は、オプティマイザーがクエリを実行するために間違ったインデックスを選択する可能性があります。
オプティマイザーが予期しないインデックスを選択する理由は複数あります。
- 古い統計:オプティマイザーはクエリコストを推定するために統計を使用します。統計が古い場合、オプティマイザーは最適ではない選択を行う可能性があります。
- 統計の不一致: 統計が最新であっても、データの分布を正確に反映していない可能性があり、コストの見積もりが不正確になる可能性があります。
- コスト計算が正しくありません: クエリ構造やデータ分散が複雑なため、オプティマイザーがインデックスの使用コストを誤って計算する場合があります。
- 不適切なエンジンの選択: 場合によっては、オプティマイザーがクエリに最適ではない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
を共有しているとします。この場合、統計情報はデータ分布を適切に反映せず、クエリのパフォーマンスに影響を与える可能性があります。
コスト情報
実行コストの詳細情報を表示するには、 EXPLAIN
とEXPLAIN ANALYZE
ステートメントをFORMAT=verbose
オプション付きで実行します。この情報から、異なる実行パス間のコストの違いを確認できます。
エンジンの選択
デフォルトでは、TiDBはコスト見積もりに基づいてテーブルアクセスにTiKVまたはTiFlashを選択します。エンジン分離を適用することで、同じクエリに対して異なるエンジンを試すことができます。
詳細についてはエンジン分離参照してください。
関数プッシュダウン
クエリパフォーマンスを向上させるため、TiDB は特定の関数をTiKV またはTiFlashstorageエンジンにプッシュダウンして実行できます。ただし、一部の関数はプッシュダウンをサポートしていないため、利用可能な実行プランが制限され、クエリパフォーマンスに影響を及ぼす可能性があります。
プッシュダウンをサポートする式については、 TiKVはプッシュダウン計算をサポートとTiFlashはプッシュダウン計算をサポート参照してください。
特定の式のプッシュダウンを無効にすることもできます。詳細については、 最適化ルールと式プッシュダウンのブロックリスト参照してください。