OracleのAutotrace機能を利用して、Index有る無しの実行計画の違いを確認してみます。
まず、Autotrace機能を利用する場合、実行ユーザーに必要なロールを付与する必要があります。
[oracle@db01 ~]$ sqlplus / as sysdba
SQL> @?/sqlplus/admin/plustrce.sql
SQL>
SQL> drop role plustrace;
ロールが削除されました。
SQL> create role plustrace;
ロールが作成されました。
SQL>
SQL> grant select on v_$sesstat to plustrace;
権限付与が成功しました。
SQL> grant select on v_$statname to plustrace;
権限付与が成功しました。
SQL> grant select on v_$mystat to plustrace;
権限付与が成功しました。
SQL> grant plustrace to dba with admin option;
権限付与が成功しました。
SQL>
SQL> set echo off
SQLスクリプトでPLUSTRACEというロールを作成します。
SQL> grant PLUSTRACE to user1;
権限付与が成功しました。
そのロールをautotraceを実行するユーザーに付与します。
SQL> set linesize 200
SQL> set autotrace on
SQL> select * from TBL1 where col1 = 10000;
COL1 COL2
---------- ----------------------------------------------------------------------------------------------------
10000 10000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
実行計画
----------------------------------------------------------
Plan hash value: 653716635
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 65 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TBL1 | 1 | 65 | 3 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_TBL1_COL1 | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL1"=10000)
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
4 physical reads
0 redo size
580 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
さて、DBユーザーで接続し、まずはindex有りの表をSELECTした場合のトレースを確認してみます。
SQLステートメントの所からindexをスキャンしてrowidを取得し、そのrowidを読み込んでいることがわかります。
また読み込み量「physical reads」「consistent gets」は少ないことがわかります。
SQL> select * from TBL2 where col1 = 10000;
COL1 COL2
---------- ----------------------------------------------------------------------------------------------------
10000 10000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
実行計画
----------------------------------------------------------
Plan hash value: 978686403
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 171 | 11115 | 4226 (1)| 00:00:51 |
|* 1 | TABLE ACCESS FULL| TBL2 | 171 | 11115 | 4226 (1)| 00:00:51 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COL1"=10000)
Note
-----
- dynamic sampling used for this statement (level=2)
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
15390 consistent gets
15386 physical reads
0 redo size
712 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
一方、Index無しの表をSELECTした場合のトレース結果です。
SQLステートメントから表をフルスキャンした後に結果を取得していることがわかります。
そのため、読み込み量「physical reads」「consistent gets」が膨大な量になっていることがわかります。
これがindex有り無しの読み込み時間の違いの原因です。
まず、Autotrace機能を利用する場合、実行ユーザーに必要なロールを付与する必要があります。
[oracle@db01 ~]$ sqlplus / as sysdba
SQL> @?/sqlplus/admin/plustrce.sql
SQL>
SQL> drop role plustrace;
ロールが削除されました。
SQL> create role plustrace;
ロールが作成されました。
SQL>
SQL> grant select on v_$sesstat to plustrace;
権限付与が成功しました。
SQL> grant select on v_$statname to plustrace;
権限付与が成功しました。
SQL> grant select on v_$mystat to plustrace;
権限付与が成功しました。
SQL> grant plustrace to dba with admin option;
権限付与が成功しました。
SQL>
SQL> set echo off
SQLスクリプトでPLUSTRACEというロールを作成します。
SQL> grant PLUSTRACE to user1;
権限付与が成功しました。
そのロールをautotraceを実行するユーザーに付与します。
SQL> set linesize 200
SQL> set autotrace on
SQL> select * from TBL1 where col1 = 10000;
COL1 COL2
---------- ----------------------------------------------------------------------------------------------------
10000 10000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
実行計画
----------------------------------------------------------
Plan hash value: 653716635
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 65 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TBL1 | 1 | 65 | 3 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_TBL1_COL1 | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("COL1"=10000)
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
4 physical reads
0 redo size
580 bytes sent via SQL*Net to client
509 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
さて、DBユーザーで接続し、まずはindex有りの表をSELECTした場合のトレースを確認してみます。
SQLステートメントの所からindexをスキャンしてrowidを取得し、そのrowidを読み込んでいることがわかります。
また読み込み量「physical reads」「consistent gets」は少ないことがわかります。
SQL> select * from TBL2 where col1 = 10000;
COL1 COL2
---------- ----------------------------------------------------------------------------------------------------
10000 10000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
実行計画
----------------------------------------------------------
Plan hash value: 978686403
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 171 | 11115 | 4226 (1)| 00:00:51 |
|* 1 | TABLE ACCESS FULL| TBL2 | 171 | 11115 | 4226 (1)| 00:00:51 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("COL1"=10000)
Note
-----
- dynamic sampling used for this statement (level=2)
統計
----------------------------------------------------------
0 recursive calls
0 db block gets
15390 consistent gets
15386 physical reads
0 redo size
712 bytes sent via SQL*Net to client
520 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
一方、Index無しの表をSELECTした場合のトレース結果です。
SQLステートメントから表をフルスキャンした後に結果を取得していることがわかります。
そのため、読み込み量「physical reads」「consistent gets」が膨大な量になっていることがわかります。
これがindex有り無しの読み込み時間の違いの原因です。

コメント