昔、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 |------------------------------------------------------------------------------------------------------