昔、NULLが入る項目にINDEXを張っても効果が無いと聞いたことがあって、NULLが入る項目にはINDEXは使わないようにしていましたが、そんなことは無く「INDEX(RANGE SCAN)」してくれます。私の勘違いだったのかもしれません。(もしかするとOracle12cから効果を発揮するようになった?)
前提条件
DESC TB_SALARY;
名前 NULL? 型
-------------- -------- ----------------------------
EMP_ID NOT NULL NUMBER(6)
DEPT_ID VARCHAR2(3)
SALARY NUMBER(9)
SELECT EMP_ID, DEPT_ID, SALARY FROM TB_SALARY ORDER BY EMP_ID;
EMP_ID DEPT_ID SALARY
---------- ------------ ----------
1 001 4000000
2 001 5000000
3 002 6000000
4 6100000
5 6200000
6 6300000
7 6400000
SELECT
TABLE_NAME, INDEX_NAME, COLUMN_NAME
FROM
ALL_IND_COLUMNS
WHERE
TABLE_NAME='TB_SALARY';
TABLE_NAME INDEX_NAME COLUMN_NAME
----------- --------------- -----------
TB_SALARY TB_SALARY_IX01 DEPT_ID
NULLが入っている項目(DEPT_ID)をWHERE句の検索条件にする
SELECT EMP_ID, DEPT_ID, SALARY FROM TB_SALARY WHERE DEPT_ID = '001';
EMP_ID DEPT_ID SALARY
---------- ------------ ----------
1 001 4000000
2 001 5000000
SQL> SET AUTOTRACE TRACEONLY
SQL> SELECT * FROM TB_SALARY WHERE DEPT_ID = '001';
実行計画
----------------------------------------------------------
Plan hash value: 2985728425
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TB_SALARY | 3 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TB_SALARY_IX01 | 3 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------