HINT如何跨越视图生效!

本文详细介绍了如何在Oracle数据库中通过HINT优化视图的执行计划,包括全表扫描、指定表名前缀等方法,以及在SQL查询中针对不同情况的有效应用,特别关注于如何针对包含视图的查询指定执行路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值