まず、質問を正しく理解していることを確認します。
- 高速化する
SELECT .. WHERE C_D IS NULL
しかし、あなたはしません NULL以外のC_Dを検索するクエリを高速化したい。 - スペースを節約するために、インデックスに「不要な」非NULL値が含まれていないことも確認する必要があります。
その理解が正しければ、必要なのは機能です。 索引。私は。フィールド自体ではなく、フィールド上の関数のインデックス...
CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS
...次にクエリを実行します...
SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
...これは...
と同等ですSELECT * FROM T WHERE C_D IS NULL
...ただし、インデックスを使用するため高速です:
これにより、単一列のインデックスにはNULLが格納されないため、スペースが節約されます。また、COMPRESS
を使用します インデックスにはキーが1つしか含まれないため、インデックス構造で同じキーを何度も繰り返すときにスペースを無駄にする必要はありません。
注:Oracle 11では、関数ベースの仮想列<を作成することもできます。 / a> (CASE
に基づく 上記の式)、次にその列に直接インデックスを付けてクエリを実行し、繰り返し入力する手間を省きます。
---編集---
C_D IS NULL
と一緒にC_Iでクエリを実行することにも関心がある場合 、できます...
CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)
...そして(たとえば)でクエリします...
SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
...これは...
と同等ですSELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL
...ただし、インデックスT_IE2
を使用するため、より高速です 。
実際、これはテーブルに必要な唯一のインデックスです(主キーを「カバー」するため、C_Iだけに個別のインデックスは必要ありません)。つまり、同じROWIDが複数のインデックスに保存されることはなく、スペースを節約できます。
注:COMPRESS
インデックスT_IE2
には意味がなくなりました 。
---編集2---
スペースよりも単純さを重視する場合は、{C_I、C_D}に複合インデックスを作成するだけです。 Oracleは、同じタプルにNULL以外の値が少なくとも1つある限り、複合インデックスにNULL値を格納します。
CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)
これはインデックスを使用します:
SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL
以前の編集と同様に、これはテーブルに必要な唯一のインデックスです。