Permettez-moi d'abord de m'assurer que j'ai bien compris la question :
- Vous voulez accélérer
SELECT .. WHERE C_D IS NULL
mais vous ne le faites pas souhaitez accélérer toutes les requêtes qui recherchent un C_D non NULL. - Vous voulez également vous assurer qu'aucune valeur non NULL "inutile" ne se trouve dans l'index, pour économiser de l'espace.
Si cette compréhension est correcte, alors ce dont vous avez besoin est un outil fonctionnel indice. C'est à dire. un index sur une fonction sur un champ, pas un champ lui-même...
CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS
...que vous interrogeriez alors comme...
SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
...ce qui équivaut à...
SELECT * FROM T WHERE C_D IS NULL
...mais plus rapide puisqu'il utilise l'index :
Cela permet d'économiser de l'espace car les index à colonne unique ne stockent pas les valeurs NULL. Utilisez également COMPRESS
puisque l'index ne contiendra jamais qu'une seule clé, il n'est donc pas nécessaire de perdre de l'espace en répétant la même clé encore et encore dans la structure de l'index.
REMARQUE :Sous Oracle 11, vous pouvez également créer une colonne virtuelle basée sur les fonctions (basé sur le CASE
expression ci-dessus), puis indexez et interrogez directement cette colonne, pour éviter une saisie répétitive.
--- MODIFIER ---
Si vous êtes également intéressé par une requête sur C_I avec C_D IS NULL
, vous pourriez...
CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)
...et l'interroger avec (par exemple)...
SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1
...ce qui équivaut à...
SELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL
...mais plus rapide, puisqu'il utilise l'index T_IE2
.
C'est en fait le seul index dont vous avez besoin sur votre table (il "couvre" la clé primaire, vous n'avez donc plus besoin d'un index séparé uniquement sur C_I). Cela signifie également qu'un même ROWID n'est jamais stocké dans plus d'un index, ce qui économise de l'espace.
REMARQUE :COMPRESS
n'a plus de sens pour l'index T_IE2
.
--- MODIFICATION 2 ---
Si vous vous souciez plus de la simplicité que de l'espace, vous pouvez simplement créer un index composite sur {C_I, C_D}. Oracle stocke les valeurs NULL dans l'index composite tant qu'il y a au moins une valeur non NULL dans le même tuple :
CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)
Ceci utilise l'index :
SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL
Comme dans l'EDIT précédent, c'est le seul index dont vous avez besoin sur votre table.