ablog

不器用で落着きのない技術者のメモ

INDEX UNIQUE SCAN と INDEX RANGE SCAN

実行計画を見てるとでてくる INDEX UNIQUE SCAN と INDEX RANGE SCAN ってなんだ?

11.5.3.2 索引一意スキャン

このスキャンは1つのROWIDしか戻しません。単一行にしかアクセスしないことが保証されているUNIQUE制約またはPRIMARY KEY制約が文に存在する場合、Oracleは一意スキャンを実行します。

例11-2「EXPLAIN PLAN出力」では、jobs表およびdepartments表で、それぞれjob_id_pk索引とdept_id_pk索引を使用して索引スキャンが実行されます

問合せオプティマイザ

11.5.3.3 索引レンジ・スキャン

索引レンジ・スキャンは、選択性の高いデータにアクセスする共通の操作です。このスキャンは、境界(両側で境界付き)スキャンまたは非有界(片側または両側で)スキャンとすることができます。データは、索引列の昇順に戻されます。同じ値を持つ複数の行は、ROWIDで昇順にソートされます。

データを一定順序でソートする必要がある場合は、ORDER BY句を使用し、索引には依存しません。索引を使用してORDER BY句を満たすことができる場合、オプティマイザはこのオプションを使用し、ソートを回避します。

問合せオプティマイザ

プライマリキーもしくはユニークインデックスになっているカラムに対してイコール検索すると、INDEX UNIQUE SCAN が使われるみたい。
普通のインデックスになっているカラムに対してイコール検索した場合と内部動作がどのように異なるんだろ?
またこんど、続きを調べよ。

ちょっとごちょごちょしてみた。

SQL> conn scott/tiger
SQL> @?/rdbms/admin/utlxplan.sql
SQL> explain plan for select ename from emp where empno = 7369;
SQL> select * from table((dbms_xplan.display(null, null)));

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------

---------------------------------------------------------------------------
| Id  | Operation                   |  Name       | Rows  | Bytes | Cost  |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |       |       |       |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP         |       |       |       |
|*  2 |   INDEX UNIQUE SCAN         | PK_EMP      |       |       |       |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------

   2 - access("EMP"."EMPNO"=7369)

Note: rule based optimization

15 rows selected.

SQL> explain plan for select ename from emp where ename = 'NEO';
SQL> select * from table((dbms_xplan.display(null, null)));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------

--------------------------------------------------------------------
| Id  | Operation            |  Name       | Rows  | Bytes | Cost  |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |       |       |       |
|*  1 |  TABLE ACCESS FULL   | EMP         |       |       |       |
--------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------


PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
   1 - filter("EMP"."ENAME"='NEO')

Note: rule based optimization

14 rows selected.

SQL> create index scott.emp_ename_idx on scott.emp (ename);
SQL> explain plan for select ename from emp where ename = 'NEO';
SQL> select * from table((dbms_xplan.display(null, null)));

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------

-----------------------------------------------------------------------
| Id  | Operation            |  Name          | Rows  | Bytes | Cost  |
-----------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                |       |       |       |
|*  1 |  INDEX RANGE SCAN    | EMP_ENAME_IDX  |       |       |       |
-----------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------


PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------
   1 - access("EMP"."ENAME"='NEO')

Note: rule based optimization

14 rows selected.

SQL> drop index emp_ename_idx;
SQL> create unique index scott.emp_ename_idx on scott.emp (ename);
SQL> explain plan for select ename from emp where ename = 'NEO';
SQL> select * from table((dbms_xplan.display(null, null)));

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------

-----------------------------------------------------------------------
| Id  | Operation            |  Name          | Rows  | Bytes | Cost  |
-----------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                |       |       |       |
|*  1 |  INDEX UNIQUE SCAN   | EMP_ENAME_IDX  |       |       |       |
-----------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------


PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------
   1 - access("EMP"."ENAME"='NEO')

Note: rule based optimization

14 rows selected.

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production
PL/SQL Release 9.2.0.7.0 - Production
CORE    9.2.0.7.0       Production
TNS for Solaris: Version 9.2.0.7.0 - Production
NLSRTL Version 9.2.0.7.0 - Production


[参考]
SQL文の実行計画を見る - bnote
スキーマ・オブジェクト
問合せオプティマイザ
Schema Objects