アクティブと非アクティブのエントリを持つテーブルがあります。アクティブはactive = 1、アクティブはactive = 0は非アクティブです。
このテーブルにはさまざまなインデックスがありますが、アプリケーションはアクティブデータに対してクエリを実行するだけなので、アクティブエントリに対してインデックスを維持するだけで済みます。非アクティブデータは再びアクティブになる可能性があるため、保持する必要がありますが、これは一般に一括更新でのみ行われます。一括更新ではインデックスを使用しません。
非アクティブなエントリ(アクティブなエントリよりもますます多くのエントリがあります)のインデックス作成にはかなりのスペースが必要です。
Oracle(10g)でこのようなことをする方法はありますか?
create index an_idx on tab (active, col1, col2, ... , coln) where active = 1
?
前回の試み
関数ベースのインデックスを使用して最初の列をnullに設定した active = 0
そのようです:
create index an_idx on tab (decode(active, 1, 1, null), col1, col2, ... , coln)
しかし、この場合、Oracleはまだ非アクティブ列に索引を付けるようです。
回答:
回答№1の場合は7ACTIVEで表をパーティション分割し、ローカル索引を作成して、非アクティブパーティションの索引をUNUSABLEにします。これにより、非アクティブデータのインデックス作成に費やす時間がなくなります。
create table tab(active number, col1 number, col2 number, col3 number)
partition by list(active)
(partition tab_active values(1), partition tab_inactive values(0));
create index tab_index1 on tab(col1) local;
alter index tab_index1 modify partition tab_inactive unusable;
しかし、このアプローチにはいくつかの潜在的な欠点があります。
- すべての種類のインデックスが使用できなくなるわけではありません。
- データベースに使用できないオブジェクトがあるのは普通のことではありません。人々はそれについて不平を言うか、それをバグだと思い、それを再構築するでしょう。
- 切り捨てなどの一部の操作では、自動的にインデックスが再び使用可能になります。
Oracle 12cでは、これを使用してこれを実現できます。 部分インデックス:
create table tab(active number, col1 number, col2 number, col3 number)
partition by list(active)
(partition tab_active values(1) indexing on,
partition tab_inactive values(0) indexing off);
create index tab_index1 on tab(col1) local indexing partial;
回答№2の11
基本的な考え方は正しいですが、デコードをすべての列に適用する必要があります。すべての添字付き式が NULL
行は索引付けされません。
create index an_idx on tab (
decode(active, 1, col1, null),
...
decode(active, 1, coln, null)
)
もちろん、このインデックスをクエリに使用したい場合は、WHERE句でも同じ式を使用する必要があります。
注:式を含める必要はないと思います decode(active, 1, 1, null)
インデックス内では、すべてのインデックス付き行に対して一定であるためです。
回答№3の場合は1
これが可能だとは思わない。いくつかの選択肢がある
- クエリ時間が影響を受けないように(active、col1 ...)にインデックスを作成します。 無効な要素による
- アクティブ/非アクティブ項目用に2つのテーブルを作成し、2つのテーブル間で物事を移動してアクティブステータスを管理します。
- インデックス付けするすべてのデータと一意の識別子を含む2番目のテーブルを作成し、そのテーブルに結合して残りのデータを取得します。