oracle的hint可以强制指定sql的执行计划:比如选择索引、表的连接顺序以及表的连接方式。不过如果查询的对象是视图,使用hint就变得麻烦一些。看一个具体的例子:
SQL> create table t1 (id number,name varchar2(30),type varchar2(30));
表已创建。
SQL> create table t2 (id number,name varchar2(30),type varchar2(30));
表已创建。
SQL> create index ind_t1_name on t1(name);
索引已创建。
SQL> create index ind_t2_name on t2(name);
索引已创建。
SQL> insert into t1 select rownum,object_name,object_type from dba_objects where object_type = 'TABLE';
已创建2793行。
SQL> insert into t2 select rownum,object_name,object_type from dba_objects where object_type = 'TABLE';
已创建2793行。
SQL> commit;
提交完成。
SQL> create view v_t as select * from t1 union all select * from t2;
视图已创建。
这里创建了一个包含union all的视图,下面对这个视图进行查询:SQL> set autotrace off;
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> set autotrace traceonly;
SQL> select * from v_t where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 932312278
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | V_T | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 6 | 282 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IND_T1_NAME | 6 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 6 | 282 | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IND_T2_NAME | 6 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
6 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
9 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
这里显然oracle 11g非常的聪明,选择了索引扫描,如果我想看一下全表扫描的效率呢?但是对于包含视图的查询,普通的hint指定方法是无效的:SQL> select /*+ full(t1) */ * from v_t where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 932312278
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | V_T | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 6 | 282 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IND_T1_NAME | 6 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 6 | 282 | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IND_T2_NAME | 6 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
6 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
9 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
正确的指定方法并不复杂,只要指定view的名称作为表明的前缀就可以了:SQL> select /*+ full(v_t.t1) */ * from v_t where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 2534531233
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | V_T | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
|* 3 | TABLE ACCESS FULL | T1 | 6 | 282 | 7 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| T2 | 6 | 282 | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | IND_T2_NAME | 6 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("NAME" LIKE 'B%')
5 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
28 consistent gets
0 physical reads
0 redo size
859 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
对于T2表也可以采用同样的方法:SQL> select /*+ full(v_t.t1) full(v_t.t2) */ * from v_t where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 680321928
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | V_T | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
|* 3 | TABLE ACCESS FULL| T1 | 6 | 282 | 7 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| T2 | 6 | 282 | 7 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("NAME" LIKE 'B%')
4 - filter("NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
47 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
如果视图中使用了别名,那么hint中指定也要使用别名:SQL> set autotrace off;
SQL> create or replace view v_t as select * from t1 a union all select * from t2 b;
视图已创建。
SQL> set autotrace traceonly;
SQL> select /*+ full(v_t.t1) full(v_t.t2) */ * from v_t where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 932312278
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | V_T | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 6 | 282 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IND_T1_NAME | 6 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 6 | 282 | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IND_T2_NAME | 6 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
6 - access("NAME" LIKE 'B%')
filter("NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
24 recursive calls
0 db block gets
65 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
SQL> select /*+ full(v_t.a) full(v_t.b) */ * from v_t where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 680321928
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | V_T | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
|* 3 | TABLE ACCESS FULL| T1 | 6 | 282 | 7 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| T2 | 6 | 282 | 7 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("NAME" LIKE 'B%')
4 - filter("NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
20 recursive calls
0 db block gets
103 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
使用hint既然可以对数据库中已经创建的视图有效,那么是否对查询中oracle临时生成的视图也有效呢?如果oracle可以将执行计划推到视图的内部,那么没有道理不支持sql语句执行过程中生成的临时视图。SQL> select * from(select * from t1 union all select * from t2) a where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 1026494751
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 6 | 282 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IND_T1_NAME | 6 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 6 | 282 | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IND_T2_NAME | 6 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."NAME" LIKE 'B%')
filter("T1"."NAME" LIKE 'B%')
6 - access("T2"."NAME" LIKE 'B%')
filter("T2"."NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
17 recursive calls
0 db block gets
63 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
在执行计划的第一步就生成了一个视图。SQL> select /*+ full(t1) full(t2) */ * from(select * from t1 union all select * from t2) a where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 1026494751
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID| T1 | 6 | 282 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IND_T1_NAME | 6 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 6 | 282 | 1 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | IND_T2_NAME | 6 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."NAME" LIKE 'B%')
filter("T1"."NAME" LIKE 'B%')
6 - access("T2"."NAME" LIKE 'B%')
filter("T2"."NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
13 recursive calls
0 db block gets
63 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed
直接指定hint显然是没有效果的,尝试使用前面介绍的方法:将查询的别名作为表名的前缀。SQL> select /*+ full(a.t1) full(a.t2) */ * from(select * from t1 union all select * from t2) a where name like 'B%';
已选择12行。
执行计划
----------------------------------------------------------
Plan hash value: 1505077622
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 47 | 0 (0)| 00:00:01 |
| 1 | VIEW | | 1 | 47 | 0 (0)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
|* 3 | TABLE ACCESS FULL| T1 | 6 | 282 | 7 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| T2 | 6 | 282 | 7 (0)| 00:00:01 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("T1"."NAME" LIKE 'B%')
4 - filter("T2"."NAME" LIKE 'B%')
Note
-----
- dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
13 recursive calls
0 db block gets
101 consistent gets
0 physical reads
0 redo size
873 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
12 rows processed