索引が存在するだけでは、必ずしもオプティマイザは索引を使用するアクセス・パスを使用するとは限りません。
索引を使用するか否かは、発行するSQLの記述方法によって左右されます。例え同一の結果を返すSQLでも、記述方法によって索引を使用する場合と使用しない場合があります。この動作はオプティマイザのアプローチによっても異なります。
以下、ルールベース・オプティマイザで索引を使用する為の基本ルールを示します。(索引列は下線で表示)
基本ルール:WHERE句で索引列値を変更した場合、索引は使用されない
例1:× SELECT ename FROM emp WHERE sal*1.1 > 950;
○ SELECT ename FROM emp WHERE sal > 950/1.1;
例2:× SELECT ename FROM emp WHERE TO_CHAR(hiredate,’YYYYMMDD’) = ’20190801’;
○ SELECT ename FROM emp WHERE hiredate = TO_DATE(’20190801’,’YYYYMMDD’);
基本ルール:索引列に対し、異なるデータ型の比較を行う場合、索引が使用されない場合がある
例1:EMPNO列がVARCHAR2型で定義してある場合
× SELECT ename FROM emp WHERE empno = 7788;
⇒ この場合内部的には以下のように変換される為、索引は使用されません
× SELECT ename FROM emp WHERE TO_NUMBER(empno) = 7788;
○ SELECT ename FROM emp WHERE empno = ’7788’;
基本ルール:検索条件にNULL値を指定した場合、索引は使用されない
*コストベース・オプティマイザで運用している場合は、ビットマップ索引を使用できます
例:
× SELECT ename FROM emp WHERE comm IS NULL;
× SELECT ename FROM emp WHERE comm IS NOT NULL;
コストベース・オプティマイザを使用した場合、WHERE句に IS NOT NULL を指定しても、ヒントによって指定した索引を使用するように指示を出すことが可能です。
◎ SELECT /*+ INDEX(emp emp_comm) */ ename FROM emp WHERE comm IS NOT NULL
索引列が NUMBER型の場合は、NULL値の代わりとなる値(0など)を設定するようにする
◎ SELECT ename FROM emp WHERE comm = 0;
(4)NOT EQUAL演算子を使用した場合基本ルール:NOT EQUAL演算子(NOT INも)を使用した検索では、索引は使用されない
例1:× SELECT ename FROM emp WHERE deptno != 30;
(5)比較演算子、またはBETWEEN演算子を使用した場合基本ルール:比較演算を行う検索でも索引は使用される
○ SELECT ename FROM emp WHERE comm >= 0;
○ SELECT ename FROM emp WHERE comm BETWEEN 500 AND 1000;
基本ルール1:複数の索引列が WHERE句で指定された場合、優先順位が一番高い索引が適用される
基本ルール2:優先順位が同じ場合は、索引のマージが行われる
基本ルール3:演算子が等価演算子以外の場合は、最後に作成された索引だけが使用される
例:empno列に一意索引、ename列、job列、depno列に非一意索引を順に作成した場合
○ SELECT ename FROM emp WHERE ename = ’SCOTT’ AND empno = 7788;
⇒ empno列の索引が使用されます
○ SELECT ename FROM emp WHERE deptno = 20 AND job = ’MANAGER’;
⇒ deptno列と job列の両方の索引が使用されます
○ SELECT ename FROM emp WHERE deptno < 30 AND empno < 7000;
⇒ 索引の作成順が最後だったdeptno列の索引が使用されます
基本ルール:OR論理演算子で指定する全ての列に索引が存在する場合のみ、索引が使用される
× SELECT ename FROM emp WHERE sal = 3000 or job = ’MANAGER’;
◎ SELECT ename FROM emp WHERE sal = 3000 or job = ’MANAGER’;
(8)LIKE演算子を使用した場合基本ルール:LIKE演算子を使用した場合、索引列が CHAR型、もしくは VARCHAR2型で前方一致の場合のみ索引が使用される
× SELECT ename FROM emp WHERE ename LIKE ’%K%’;
◎ SELECT ename FROM emp WHERE ename LIKE ’S%’;
基本ルール:IN 演算子を使用した場合、索引は使用されるが、NOT IN 演算子の場合は使用されない
× SELECT ename FROM emp WHERE deptno NOT IN (10,20);
◎ SELECT ename FROM emp WHERE deptno IN (10,20);
基本ルール:DISTINCT句に対して索引は使用されない
× SELECT DISTINCT empno FROM emp;
(11)ORDER BY句を使用した場合基本ルール:特定の場合のみ使用される
以下の条件を全て満たす
ORDER BY句で指定した列に PRIMARY KEY 制約もしくは NOT NULL 制約が定義されているWHERE句に索引を使用できる構文を含んでいない場合 SQL>DESC emp Name Null? Type ------------------------- -------------------------- ----------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2)△ SELECT ename FROM emp WHERE deptno = 20 ORDER BY empno;
⇒ deptno列の索引が使用される
◎ SELECT ename FROM emp ORDER BY empno;
⇒ empno列の索引が使用される
基本ルール:特定の場合のみ使用される
以下の条件を全て満たす
MAX (MIN) が唯一の選択リストの場合問い合わせが結合でない場合WHERE 句、GROUP BY 句が使用されていない場合例:
× SELECT MAX(sal) FROM emp WHERE deptno = 20;
◎ SELECT MAX(sal) FROM emp;
基本ルール:特定の場合のみ使用される(コストベース・オプティマイザのみ)
表の列に NOT NULL 制約が定義されていて、以下のどちらかの条件を満たす
例:EMP表の empno列には NOT NULL 制約が定義されている
◎ SELECT COUNT(*) FROM emp;
◎ SELECT COUNT(empno) FROM emp;
基本ルール:特定の場合のみ使用される(コストベース・オプティマイザのみ)
以下の条件を全て満たす
選択リストの列と GROUP BY句で指定した列のコンポジット索引が存在する場合(但し先頭列は GROUP BY句で指定した列) GROUP BY句で指定した列に NOT NULL 制約が定義されている例:EMP表の deptno列には NOT NULL 制約が定義されている。また、deptno列にコンポジット索引が定義されている。
◎ SELECT deptno,MAX(sal) FROM emp GROUP BY deptno;
(15)HAVING句を使用した場合基本ルール:HAVING句に対して索引は使用されない
× SELECT deptno,COUNT(*) FROM emp GROUP BY deptno HAVING deptno = 30;
可能であれば、WHERE 句に書き換えて索引を使用するようにする。
◎ SELECT deptno,COUNT(*) FROM emp WHERE deptno = 30 GOUP BY deptno;
(16)コンポジット索引を使用した場合基本ルール:検索条件にコンポジット索引の先頭列が含まれている場合のみ使用される(先頭列とは、CREATE INDEX文の列リストの1つ目の列を意味する)
例: CREATE INDEX i_sample ON sample (col1, col2, col3);
col1 列に NOT NULL 制約が定義されている場合
◎ SELECT col1 FROM sample WHERE col1 = 10;
◎ SELECT col1 FROM sample WHERE col1 = 10 AND col2 = 20;
◎ SELECT col1 FROM sample WHERE col1 = 10 AND col2 = 20 AND col3 = 30;
◎ SELECT col1 FROM sample WHERE col1 = 10 AND col3 = 30;
◎ SELECT col1 FROM sample ORDER BY col1;
◎ SELECT col1 FROM sample ORDER BY col1,col3;
× SELECT col1 FROM sample WHERE col2 = 20 AND col3 = 30;
× SELECT col1 FROM sample WHERE col3 = 30;