2009-12-10 7 views
7

私は、最大5.000.000行の可能性を持つテーブルを持っています。この表の列の1つは照会で単独で使用されますが、この列には5つの可能な値があり、現在は10.000行があり、Explain計画に従ってその列に自分の索引を使用することは意味がありません。5つの異なる値を持つ列の索引 - 価値があるか?

今までそれをウィル、または私は、インデックスを気にしてはならない

編集:これは、2つの現時点での計画を説明している Without index http://img706.imageshack.us/img706/1903/noindex.pngWith forced index via hints http://img692.imageshack.us/img692/8205/indexp.png 私は、インデックスの使用を強制的に後者の画像ヒント付き。

+0

もちろん、質問にもよりますが、この例では、FREQUENCYIDという1つの条件でフィルタリングする場合を示します。後で(おそらく動的クエリを使用して)他の基準を持つことが予想され、それによってフィルタリングされる場合は、インデックスが理にかなっています。 –

答えて

7

これはいくつかのことによって異なります。

まず、値の分布。 5つの別個の値しか持たないが、そのうちの1つがテーブルの行の99.9999%を占める場合、明らかにオプティマイザがその値のインデックスを使用することを望まないでしょうが、かもしれないは、このような場合には、関数ベースの索引を使用して、関心のある値のみを索引付けし、スペースを取っているものは索引化しないようにしてください。

第2に、テーブルにアクセスせずにそのインデックスを使用して回答できるクエリはありますか?

重要なのはアクセスされる行の割合だけでなく、アクセスする必要のあるテーブルのブロック数です。たとえば、平均1000ブロックと30行のテーブルがあり、1つの列に30個の異なる値(それぞれが1000行に存在する)がある場合、すべての行を読み込むために訪問する必要があるブロックの数1つの値は、行の分散方法に応じて、1000/30 = 34(索引を使用する価値があります)と1000(索引を使用する価値がない)の間で変化します。これはインデックスのクラスタ化係数で表されます。値がテーブル内の行数に近い場合、インデックスは使用される可能性が低く、ブロック数に近い場合は、中古。

また、インデックス圧縮を参照してスペースを節約できるかどうかを確認することもできます。

ビットマップインデックスに注意してください。同時に複数のセッションによって変更されるシステム(たとえば、2人が同時にインデックス付きテーブルに行を挿入するなど)には向いていません。

これらの5つの値に対する述部を持つ照会の効率を改善したい場合、より効果的な戦略は、部分的には照会のパーティション・プルーニングのためですが、オプティマイザーが使用できる統計の改善1つのパーティションだけがアクセスされ、グローバル統計の代わりにパーティションレベル統計を使用できることがわかります。

1

あなたが5.000.000行

まで

に言及してサイズが大きくなるためにやっている場合は、私は、インデックスを作成するお勧めします。

1

おそらく最も簡単な方法ではなく、実際に試してみてください。

しかし、最良のアプローチを見つけるために実行計画を比較しているようです。それは信頼できません。オプティマイザは、最適なプランを選択するための適切な情報を持っていない可能性があります(たとえば、値が不均一で、ヒストグラムがないなど)。また、説明計画の "コスト"を見ても意味がありません。

より良い方法は、論理IOを比較することです。 SQL * Plusを実行して、set autotrace traceonlyと入力し、問合せを実行して(索引の有無にかかわらず)「一貫性取得」の数値を比較します。それほど良いことはありません。

LIOの重要性について:article by Cary Millsap

0

典型的なクエリでテストします。どの方法が高速かを確認してください。

フル・テーブル・スキャンは、索引レンジ・スキャン+ Rowidによるテーブル・アクセスよりも平均的に高速であることがあります。この場合、Oracleは正しいと判断します。

一方、大部分のクエリではインデックスを使用するほうが良いデータパターンがあります。この場合、おそらくINDEXヒントを追加することになります。

2

インデックスは次のような場合に有用であろう:

  • あなたはまれFREQUENCYID年代を検索します。同様に、10,000,000行の10にはFREQUENCYID = 1があり、それを検索します。

  • クエリでFREQUENCYID以外の列を使用しない場合。このクエリ:

    SELECT FREQUENCYID, COUNT(*) 
    FROM mytable 
    GROUP BY 
         FREQUENCYID 
    

    は、あなたのテーブルの行が大きく、クエリで使用するすべての列が索引付けされたインデックス(実際には、HASH AGGREGATEとともにINDEX FAST FULL SCANはおそらく使用されます)

  • 恩恵を受けることができます。この方法では、FULL TABLE SCANの代わりにすべてのインデックスが結合されます。このクエリを言う:

    SELECT FREQUENCYID, OTHERCOLUMN 
    FROM mytable 
    WHERE FREQUENCYID = 2 
    

    ROWIDFREQUENCYIDOTHERCOLUMNのインデックスの値を結合することによって行うことができます。

関連する問題