您可以在针对视图的查询中使用提示,以强制Oracle使用基表上的索引。但您需要知道底层视图中基本表的别名(如果有的话)。一般的语法是:
/*+ index(<<从查询中得到的视图别名>> <<从视图中得到的表别名>> <<索引名称>>) */
例如:
1)创建一个带有10,000条相同记录的表,并在该表上创建一个索引。由于索引不具有选择性,因此Oracle不会使用它。
SQL> ed
Wrote file afiedt.buf
1 create table foo
2 as
3 select 1 col1
4 from dual
5* connect by level <= 10000
SQL> /
Table created.
SQL> create index idx_foo on foo(col1);
Index created.
2) 确认该索引通常不被使用但Oracle将使用提示来使用它
SQL> set autotrace traceonly;
SQL> select * from foo where col1 = 1;
10000 rows selected.
Execution Plan
Plan hash value: 1245013993
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 126K| 7 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| FOO | 10000 | 126K| 7 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("COL1"=1)
Note
- dynamic sampling used for this statement (level=2)
Statistics
9 recursive calls
0 db block gets
713 consistent gets
5 physical reads
0 redo size
172444 bytes sent via SQL*Net to client
7849 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processed
SQL> select *
2 from foo
3 where col1 = 1;
10000 rows selected.
Execution Plan
Plan hash value: 15880034
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 126K| 25 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| IDX_FOO | 10000 | 126K| 25 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("COL1"=1)
Note
- dynamic sampling used for this statement (level=2)
Statistics
7 recursive calls
0 db block gets
715 consistent gets
15 physical reads
0 redo size
172444 bytes sent via SQL*Net to client
7849 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processed
3) 现在创建视图。通过指定查询中的视图别名和视图定义中的表别名来强制使用索引,验证对视图的普通查询不使用索引。
SQL> create view vw_foo
2 as
3 select col1
4 from foo f;
View created.
SQL> select col1
2 from vw_foo
3 where col1 = 1;
10000 rows selected.
Execution Plan
Plan hash value: 1245013993
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 126K| 7 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| FOO | 10000 | 126K| 7 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - filter("COL1"=1)
Note
- dynamic sampling used for this statement (level=2)
Statistics
16 recursive calls
0 db block gets
715 consistent gets
0 physical reads
0 redo size
172444 bytes sent via SQL*Net to client
7849 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processed
SQL> select col1
2 from vw_foo vf
3 where col1 = 1;
10000 rows selected.
Execution Plan
Plan hash value: 15880034
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 10000 | 126K| 25 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| IDX_FOO | 10000 | 126K| 25 (0)| 00:00:01 |
Predicate Information (identified by operation id):
1 - access("COL1"=1)
Note
- dynamic sampling used for this statement (level=2)
Statistics
14 recursive calls
0 db block gets
717 consistent gets
0 physical reads
0 redo size
172444 bytes sent via SQL*Net to client
7849 bytes received via SQL*Net from client
668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10000 rows processed
SQL>
尽管如此,一般来说,提示是在调整查询时的最后一个选择--通常更好的方法是找出优化器缺少的信息,并提供适当的统计数据,以便它可以自己做出正确的选择。这是一个更加稳定的解决方案。在涉及多层别名的提示中,如果你被迫使用提示,那么很容易因为某人更改表名的别名而破坏你的查询,例如。