web-dev-qa-db-ja.com

Oracleインデックスを選択して最適化する方法

索引を作成するための一般的なルールがあるかどうか知りたいのですが。このインデックスに含める必要があるフィールドを選択するにはどうすればよいですか?

環境とデータ量に常に依存することは知っていますが、Oracleでインデックスを作成することについて、世界的に認められているルールを作成できるかどうか疑問に思っていました。

28
guigui42

Oracleのドキュメントには、インデックスの選択に関する一連の優れた考慮事項があります。 http://download.Oracle.com/docs/cd/B28359_01/server.111/b28274/data_acc.htm#PFGRF004

引用:

  • WHERE句で頻繁に使用されるキーにインデックスを付けることを検討してください。

  • SQLステートメントでテーブルを結合するために頻繁に使用されるキーにインデックスを付けることを検討してください。結合の最適化の詳細については、「パフォーマンスのためのハッシュクラスタの使用」を参照してください。

  • 選択性の高いインデックスキーを選択します。インデックスの選択性は、インデックス付きキーに対して同じ値を持つテーブル内の行の割合です。インデックスの選択性は、同じ値を持つ行が少ない場合に最適です。注意:Oracleは、整合性制約を使用して定義した一意キーと主キーのキーおよび式に、索引を自動的に作成するか、既存の索引を使用します。 1つまたは2つの値が他の値よりもはるかに少ない頻度で発生するようにデータ分布が偏っている場合、選択度の低い列のインデックスを作成すると便利です。

  • 明確な値がほとんどないキーまたは式には、標準のBツリーインデックスを使用しないでください。このようなキーまたは式は通常、選択性が低く、頻繁に選択されるキー値が他のキー値よりも頻繁に表示されない限り、パフォーマンスを最適化しません。同時実行性が高いOLTPアプリケーションのように、インデックスが頻繁に変更されない限り、ビットマップインデックスを効果的に使用できます。

  • 頻繁に変更される列にインデックスを付けないでください。インデックス付きの列を変更するUPDATEステートメントと、インデックス付きのテーブルを変更するINSERTおよびDELETEステートメントは、インデックスがない場合よりも時間がかかります。このようなSQLステートメントは、テーブル内のデータだけでなく、インデックス内のデータも変更する必要があります。また、追加の取り消しとやり直しも生成します。

  • 関数または演算子を含むWHERE句でのみ表示されるキーにインデックスを付けないでください。 MINまたはMAX以外の関数、またはインデックス付きキーを持つ演算子を使用するWHERE句は、関数ベースのインデックスを除いて、インデックスを使用するアクセスパスを利用可能にしません。

  • 多数の同時INSERT、UPDATE、およびDELETEステートメントが親テーブルと子テーブルにアクセスする場合は、参照整合性制約の外部キーにインデックスを付けることを検討してください。このようなインデックスを使用すると、子テーブルを共有ロックすることなく、親テーブルでUPDATEおよびDELETEを実行できます。

  • キーにインデックスを付けることを選択するときは、クエリのパフォーマンス向上がINSERT、UPDATE、DELETEのパフォーマンス低下と、インデックスの格納に必要なスペースの使用に見合う価値があるかどうかを検討してください。インデックスを使用した場合と使用しない場合のSQLステートメントの処理時間を比較して実験することをお勧めします。 SQLトレース機能を使用して、処理時間を測定できます。

52
David Aldridge

常にインデックスを作成する必要のある事項がいくつかあります。

  • 主キー-これらにはインデックスが自動的に与えられます(Oracleが使用する適切な既存のインデックスを指定しない限り)
  • 一意のキー-これらには自動的にインデックスが付けられます(同上)
  • 外部キー-これらはnotに自動的にインデックスが付けられますが、制約がチェックされるときのパフォーマンスの問題を回避するために1つ追加する必要があります

その後、クエリのフィルタリングに頻繁にが使用されている他の列を探します。典型的な例は、人の姓です。

10
Tony Andrews

10g Oracle Database Application Developers Guide-Fundamentals、第5章から:

一般に、次のような状況では、列にインデックスを作成する必要があります。

  • 列は頻繁に照会されます。
  • 列に参照整合性制約が存在します。
  • 列にUNIQUEキー整合性制約が存在します。

インデックスを作成するタイミングを決定するには、次のガイドラインを使用します。

  • 大きなテーブルの行の15%未満を頻繁に取得する場合は、インデックスを作成します。ただし、このしきい値のパーセンテージは、テーブルスキャンの相対的な速度と、インデックスキーに関する行データのクラスター化の度合いによって大きく異なります。テーブルスキャンが高速であるほど、割合は低くなります。行データがクラスター化されるほど、パーセンテージが高くなります。
  • 結合のパフォーマンスを向上させるために結合に使用される列にインデックスを付けます。
  • 主キーと一意キーには自動的にインデックスがありますが、外部キーにインデックスを作成することもできます。詳細は、第6章「アプリケーション開発におけるデータ整合性の維持」を参照してください。
  • 小さなテーブルはインデックスを必要としません。クエリに時間がかかりすぎる場合は、テーブルが小さいサイズから大きいサイズに大きくなっている可能性があります。

一部の列は、インデックス作成の強力な候補です。以下の1つ以上の特性を持つ列は、索引付けの適切な候補です。

  • 値が列で一意であるか、重複がほとんどありません。
  • 値の範囲が広い(通常のインデックスに適しています)。
  • 値の範囲が狭い(ビットマップインデックスに適しています)。
  • 列には多くのnullが含まれますが、クエリは多くの場合、値を持つすべての行を選択します。この場合、次のようなnull以外のすべての値と一致する比較。

    WHERE COL_X> = -9.99 * power(10,125)はWHERE COL_X IS NOT NULLよりも望ましい

    これは、最初のものがCOL_Xのインデックスを使用するためです(COL_Xが数値列であると想定)。

以下の特性を持つ列は、索引付けにはあまり適していません。

  • 列に多くのnullがあり、null以外の値を検索しません。
4
DCookie

うわー、これは非常に大きなトピックなので、この形式で答えることは困難です。私はこれを強くお勧めします book

タピオ・ラーデンマキによるリレーショナルデータベースのインデックスデザインとオプティマイザ

インデックスを使用してテーブルアクセスを高速化するだけでなく、インデックスを作成してテーブルアクセスを完全に回避する場合もあります。まだ言及されていないが重要です。

データベースを最大限に活用したい場合、これには完全な科学があります。

ああ、Oracleに対する特定の最適化の1つは、逆キーインデックスの構築です。シーケンスのように、単原子的に増加する値のPKインデックスがあり、同時挿入が非常に多く、その列を範囲スキャンする予定がない場合は、その列を逆キーインデックスにします。

これらの最適化がどれほど具体的であるかをご覧ください。

2
Mark Brady

データベースの正規化を調べてください。どのキーが存在する必要があるか、データベースをどのように関連付ける必要があるか、インデックスに関するヒントについて、業界標準の優れたルールがたくさん見つかります。

-アダム

1
Adam Davis

通常、ID列を前に配置し、それらは通常、行を一意に識別します。列の組み合わせでも同じことができます。例として、cars ...タグまたはナンバープレートを使用すると、一意になり、インデックスの対象になります。それら(タグ列)は主キーの対象となります。名前で検索する場合、所有者の名前はインデックスの対象になります。 makeの車はあまり変化しないので、最初は本当にインデックスを取得すべきではありません。列のデータがあまり変化しない場合、インデックスは役に立ちません。

SQLを見てみましょう-where句は何を調べていますか。それらはインデックスを必要とするかもしれません。

測定。問題は何ですか-ページ/クエリに時間がかかりすぎますか?クエリに使用されているもの。それらの列にインデックスを作成します。

警告:インデックスは更新とスペースのために時間が必要です。

場合によっては、テーブル全体のスキャンがインデックスよりも高速です。小さなテーブルは、インデックスを取得してテーブルにアクセスするよりも速くスキャンできます。結合を見てください。

0
jim