web-dev-qa-db-ja.com

Oracleの範囲クエリの日付列のインデックス?

たくさんあります:

select count(*) from TBL where XDATE between ? and ? and FLD = ?;

[〜#〜] xdate [〜#〜]列([〜#〜] date [〜#〜]タイプの列でインデックスを調整することにより、パフォーマンスを向上させることが期待されます)。

[〜#〜] date [〜#〜]タイプおよびbetween条件により適したインデックスのタイプは何ですか?

3
gavenkoa

詳細が提供されると、2列のインデックスが賢明になります。

CREATE INDEX tbl_index ON tbl(fld,xdate);

しかしもちろん、すべてがデータに依存します。

  • クエリがテーブルのフルスキャンの1%以上を返す場合、おそらく最も高速になります。したがって、インデックスを作成する必要はまったくありません
  • fLDの選択性が低い場合、(xdate)のインデックスで同様の結果が得られる可能性があります
  • すべてのインデックスは、DML操作にオーバーヘッドを追加します。データの変更に加えて、Oracleはすべてのインデックスを変更し、すべてをREDOログに記録する必要があります。

データを収集するには、次のコマンドを実行します。

select count(*) from TBL;
select count(*) from TBL where XDATE between ? and ?;
select count(*) from TBL where FLD = ?;
select count(*) from TBL where XDATE between ? and ? and FLD = ?;

結果を比較します。または、それらの結果で質問を編集します。

2

範囲-特に日付範囲-は調整が難しい場合があります。これには一言の違いがあります...

_where xdate between date '2013-07-01' and date '2013-07-31'
_

... この ...

_where xdate between date '2003-07-01' and date '2013-07-31'
_

これら2つのクエリには、根本的に異なるアクセスパスが必要です。インデックスは最初のインデックスには役立ちますが、2番目のインデックスではおそらく悲惨なものになります(関係するデータの量によって異なります)。

インデックス付けの日付に関する他の問題は、時間要素に関係しています。 xdateに時間要素が含まれている場合、各暦日に86400の異なる値がある可能性があります。ほとんどの場合、日付範囲検索を行っているときは、時間に関係なくdayのすべてのヒットが必要です。

詳細を十分に提供していないため、絶対的な推奨はできませんが、私の一般的なアドバイスは次のとおりです。

  1. 関数ベースのインデックスを作成し、時間要素を削除します:create index tbl_xdate_idx on tbl(trunc(xdate))
  2. インデックスの圧縮によってスペースを節約できるかどうかを調べます。圧縮されたインデックスは通常、パフォーマンスも向上します。しかし、日付が時間を含まない場合にのみ価値があると思われます。これは、FBIアプローチのもう1つの利点です。ああ、あなたはEnterprise Editionが必要です。
  3. 長い範囲にわたる検索は、別の方法で処理する必要がある場合があることに注意してください。その方法は、アプリケーションの特性によって異なります。
5
APC