2

が付いたテーブルがあるとしましょう50 columns。私は次のようなことをしたい:

SELECT * FROM table WHERE column1=value1 OR column2=value2 OR ...

どうすればこれを効率的に行うことができますか?

  1. indexes多くの/すべての列に多数またはインデックスを追加できます。これは役に立ちますか?

  2. secondary table列( )を使用してを作成し、id, field_name, field_value各列にインデックスを付けることができます。これで、ORはインデックスが付けられた2つの列にのみ適用されます。

  3. 他に何ができますか?

もう少し詳しい情報:

  • 行はかなり頻繁に追加されますが、その後編集されることはめったにありません。
  • 行は追加された後に数回選択されます(おそらく数十、おそらく数百ではありません)。
  • テーブルには100,000以上の行があり、テーブルスキャンが遅すぎます。
  • 具体的には、行が与えられた場合、任意の列でその行に一致するすべての行を検索する必要があります。
4

2 に答える 2

0

このようなシナリオに遭遇した場合、通常、テーブルを正規化する余地があることを示しています (シナリオ B)。列が実際に保持しているデータと、全体的なテーブル アクセス パターンについての詳細な情報がなければ、知ることは困難です。

そうは言っても、テーブル構造を変更しなくても、テーブル全体のスキャンを防ぐために、クエリを実行する可能性のある各列にインデックスを作成するだけで済みます。

于 2012-12-20T23:27:55.597 に答える
0

データベース設計の変更に関する議論はさておき...


結合されたインデックス (クエリで参照される列の多くまたはほとんどのインデックス) は、OR'dcolN = 'foo'述語がたくさんあるクエリには役に立ちません。MySQL は、クエリを満たすためにそのインデックスを使用しません。インデックスを使用する場合でも、基礎となるテーブルには基本的にすべての行をチェックする必要がある他の列が存在するため、MySQL はすべてのデータ ページを参照するだけで、インデックスをまったく使用しない可能性が非常に高くなります。(クエリに GROUP BY または ORDER BY が含まれている場合、MySQL はインデックスを使用してこれらの操作を最適化できる可能性があります。特に、クエリによって参照される EVERY カラムを含む「カバーする」インデックスである場合は.

一方、 でチェックされた EVERY 列 (インデックスの先頭の列として) に個別の個別のインデックスOR colN = 'foo' OR colN = 'bar'がある場合、MySQL はクエリに「インデックス マージ」プランの使用を検討する可能性があります。

ただし、すべての列のインデックスである必要があります。クエリが、任意のインデックスの先頭の列ではない 1 つの列だけでもチェックする場合、MySQL はテーブル内のすべての行を調べるしかありません。したがって、「多くの」列に個別のインデックスを使用しても、クエリには役立ちません。これは、インデックスがどれも使用されない可能性が非常に高いためです。

参照される列のボートロードのすべてに個別のインデックスがあったとしても、(各インデックスから結合された) 返される行の総数の MySQL の見積もりが大きすぎる可能性があり、MySQL はそれを決定する可能性があります。 「インデックス マージ」はコストがかかりすぎるため、代わりに全テーブル スキャンを選択します。


要約すると、クエリに役立つインデックスの選択肢は 2 つだけです (どちらも良い選択ではありません)。

1) GROUP BY または ORDER BY 句を満たすために使用できる先行列を持つ「カバリング インデックス」(「ファイルソートの使用」操作を回避する)

OR colN = 'literal'2)クエリの述語によってチェックされるすべての列(先頭の列として)の個別の個別のインデックス

しかし、繰り返しになりますが、どちらも良い選択ではありません。

于 2012-12-21T00:06:23.210 に答える