Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Oracle 11 Index apenas para parte dos dados


Antes de mais nada, veja se entendi a pergunta corretamente:
  • Você deseja acelerar SELECT .. WHERE C_D IS NULL mas você não deseja acelerar qualquer uma das consultas que pesquisam um C_D não NULL.
  • Você também deseja garantir que nenhum valor "desnecessário" não NULL esteja no índice, para economizar espaço.

Se esse entendimento estiver correto, então o que você precisa é de um funcional índice. Eu. um índice em uma função em um campo, não um campo em si...
CREATE INDEX T_IE1 ON T (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) COMPRESS

...que você então consultaria como...
SELECT * FROM T WHERE (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1

...que é equivalente a...
SELECT * FROM T WHERE C_D IS NULL

...mas mais rápido, pois usa o índice:



Isso economiza espaço porque os índices de coluna única não armazenam NULLs. Além disso, use COMPRESS já que o índice sempre conterá apenas uma chave, portanto, não há necessidade de desperdiçar espaço repetindo a mesma chave várias vezes na estrutura do índice.

NOTA:No Oracle 11, você também pode criar uma coluna virtual baseada em função (baseado no CASE expressão acima), indexe e consulte essa coluna diretamente, para salvar algumas digitações repetitivas.

--- EDITAR ---

Se você também estiver interessado em consultar C_I junto com C_D IS NULL , você poderia...
CREATE UNIQUE INDEX T_IE2 ON T (C_I, CASE WHEN C_D IS NULL THEN 1 ELSE NULL END)

... e consulte com (por exemplo) ...
SELECT * FROM T WHERE C_I > 'some value' AND (CASE WHEN C_D IS NULL THEN 1 ELSE NULL END) = 1

...que é equivalente a...
SELECT * FROM T WHERE C_I > 'some value' AND C_D IS NULL

...mas mais rápido, pois usa o índice T_IE2 .

Este é de fato o único índice que você precisa em sua tabela (ele "cobre" a chave primária, então você não precisa mais de um índice separado apenas em C_I). O que também significa que um mesmo ROWIDs nunca é armazenado em mais de um índice, o que economiza espaço.

NOTA:COMPRESS não faz mais sentido para o índice T_IE2 .

--- EDITAR 2 ---

Se você se preocupa mais com a simplicidade do que com o espaço, basta criar um índice composto em {C_I, C_D}. O Oracle armazena valores NULL no índice composto desde que haja pelo menos um valor não NULL na mesma tupla:
CREATE UNIQUE INDEX T_IE3 ON T (C_I, C_D)

Isso usa o índice:
SELECT * FROM T WHERE C_I > 1 AND C_D IS NULL

Como no EDIT anterior, este é o único índice que você precisa em sua tabela.