Se o índice for BITMAP, sua utilização em uma busca será utilizada tanto pelo COUNT quanto pela busca direta pelos valores NULL, conforme comentado pelo Luis Santos na postagem Lendas de Oracle Tuning: busca por NULL não utiliza índice.
C:\Users\ricar>sqlplus RICARDO/Nerv2017@localhost/DEV SQL*Plus: Release 12.2.0.1.0 Production on Seg Jun 19 10:07:20 2017 Copyright (c) 1982, 2016, Oracle. All rights reserved. Conectado a: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production SQL> CREATE TABLE T1 AS SELECT * FROM ALL_OBJECTS; Tabela criada. SQL> SELECT COUNT(*) FROM T1; COUNT(*) ---------- 64174 SQL> CREATE BITMAP INDEX IDX1_T1 ON T1(OBJECT_TYPE); ═ndice criado. SQL> UPDATE T1 SET OBJECT_TYPE = NULL WHERE OBJECT_TYPE = 'SYNONYM'; 12155 linhas atualizadas. SQL> COMMIT; Commit concluÝdo. SQL> SET AUTOTRACE TRACEONLY EXPLAIN SQL> SELECT COUNT(*) FROM T1 WHERE OBJECT_TYPE IS NULL; Plano de ExecuþÒo ---------------------------------------------------------- Plan hash value: 4029037477 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 10 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 10 | | | | 2 | BITMAP CONVERSION COUNT | | 1 | 10 | 1 (0)| 00:00:01 | |* 3 | BITMAP INDEX SINGLE VALUE| IDX1_T1 | | | | | --------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("OBJECT_TYPE" IS NULL) SQL> SELECT OBJECT_ID FROM T1 WHERE OBJECT_TYPE IS NULL; Plano de ExecuþÒo ---------------------------------------------------------- Plan hash value: 4022879359 ----------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ----------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 15 | 1 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | 1 | 15 | 1 (0)| 00:00:01 | | 2 | BITMAP CONVERSION TO ROWIDS | | | | | | |* 3 | BITMAP INDEX SINGLE VALUE | IDX1_T1 | | | | | ----------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("OBJECT_TYPE" IS NULL) SQL>
Outra forma de “indexar” null seria na criação do indice colocar um valor padrão, como por exemplo:
CREATE TABLE temp_teste_5 AS
SELECT round(dbms_random.value(1,10)) ID,
CAST (dbms_random.STRING(‘U’,10) AS VARCHAR2(10)) NOME,
MOD(ROWNUM,5) CLASSE
FROM DUAL
CONNECT BY LEVEL <= 1000;
UPDATE temp_teste_5 set classe = null
where classe = 0
create index temp_teste_5_idx1 on temp_teste_5(classe) — apenas com o campo que tem null, logo faz Table Full Scan
select /* idx1 */ * from temp_teste_5
where classe is null
create index temp_teste_5_idx2 on temp_teste_5(classe,0) — com um valor apos a colunas para forçar a "indexação de null" e agora fará um range scan
select /* idx2 */ * from temp_teste_5
where classe is null
Excelente Jefferson. Muito obrigado pela contribuição.