我有一个视图,我想像这样查询我的视图以暗示基表中的某些索引,我可以这样做吗?
我的意思是:
--view
create or replace view temp_view
as select col1,col2,col3
from table1,table2....
我在 table1.col1 上有一个 index,名为“index1”。
我有一个查询:
--query
select *
from temp_view
where col1=12;
当我看到这个查询的解释计划时,它告诉我查询不使用“index1”,我想指出它..
所以我希望它是,例如:
--query with hint
select /*+ index(temp_view index1)*/*
from temp_view
where col1=12;
我可以指出视图提示吗? (如果我不想在创建此视图时指出它)
您可以在针对视图的查询上使用提示来强制 Oracle 使用基表上的索引。但是您需要知道基础视图中基表(如果有)的别名。一般语法是
/*+ index(<<alias of view from query>> <<alias of table from view>> <<index name>>) */
一个例子
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 /*+ index(foo idx_foo) */ *
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 /*+ index(vf f idx_foo) */ 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>
尽管如此,提示通常是尝试调整查询时的最后手段——通常最好找出优化器缺少哪些信息并提供适当的统计信息,以便它可以自行做出正确的选择。这是一个更加稳定的解决方案。更重要的是,当您减少到指定涉及多层别名的提示时,例如,对于接触视图定义的人来说,通过更改表名的别名来破坏您的查询太容易了。
我尝试了 Justin Cave 的(旁边的答案)语法
select /*+ index(vf f idx_foo) */ col1
from vw_foo vf
where col1 = 1;
,但这对我不起作用。接下来就成功了
select /*+ index(vf.f idx_foo) */ col1
from vw_foo vf
where col1 = 1;
我尝试过 Oracle Database 11g 企业版版本 11.2.0.1.0 - 64 位生产版
完美,谢谢你的解释。请注意 Oracle 19c - 此表示法不适用于 ANSI JOIN(使用 JOIN ... ON ... LEFT JOIN ... ON .. 进行连接的语法)。 对于这种情况,应该使用解释计划中的别名(alias@qb_name)。