ITPub博客

首页 > 数据库 > Oracle > 034.笔记:基本的提示语法

034.笔记:基本的提示语法

原创 Oracle 作者:limintjhn 时间:2013-01-06 19:57:25 0 删除 编辑

1.最常用的提示
最常用的10个提示:
INDEX
ORDERED
PARALLEL
FIRST_ROWS
RULE
FULL
LEADING
USE_NL
APPEND
USE_HASH
1.1 谨慎使用提示
提示可以分为两个主要类别:应用指令(usage directive)和编译器指令(compliler directive)。
应用指令是指在init.ora级别或系统参数文件(SPFILE)而不是语句级别中设置的提示(比如FIRST_ROWS到ALL_ROWS)。
如果您有一个OLTP(在线事务处理)数据库,那就是可以直接设置CHOOSE到FIRST_ROWS为优化器(在实例 级别中),使得优化器可以更快地返回最初的几行
(对于大多数OLTP应用程序来说最短的响应时间)。做到这点可以有很多方法,但最主要的方法是以嵌套循环方式来执行连接。
设置直接到ALL_ROWS的优化器(在实例级别),使得优化器可以很快地返回所有行(对于所有行来说最佳的吞吐量,这可能适合于批处理操作或数据仓库)。
您向优化器提供的提示会影响对于连接操作和操作顺序的选择。在上面两种数据库(OLTP和数据仓库)中,目的都是要在系统范围内解决性能问题,而不是要
调整每一个查询。

当数据仓库中有很多行为类似于OLTP中的查询或者OLTP中有许多类似于数据仓库中的查询时,这时就可以对这些具体的语句使用提示。一旦开始使用提示,您
将会发现需要反复地调整同样的问题。这可能是存在影响性能的不适当的实例级设置或不适当的数据库结构(例如,缺少索引或I/O争用)。调整这些症状(在
短期内使用使用编译指令)将决定您在长期内使用的模式。可以使用应用指令在系统范围内修正问题。如果您多注意这些方面,那就可以减少使用提示的次数。

1.2 首先修正设计方案
STUDENT primary key student_id
class primary key class_id
student_class concatenated primary key of (class_id,student_id)
student_class secondary index on (student_id,class_id)
设计索引结构支持多个访问路径,从而可以向优化器提供用于选择最佳执行路径的工具。


2.可用的提示和分组
2.1改变执行路径
实例级的参数OPTIMIZER_MODE可用于修改数据库中的所有语句,使其遵循特定的执行路径。
改变执行路径的提示如下所示:
ALL_ROWS
FIRST_ROWS(n)
2.2使用访问方法提示
访问方法组中的提示允许编码人员改变访问实际查询的方式。需要经常使用这组提示,特别是INDEX提示。它可以直接指出是否需要使用索引以及如何使用索引,以及
如何将对应的索引合并起来以得到最终的结果。下面列出这组访问方法提示:
CLUSTER
FULL
HASH
INDEX
INDEX_ASC
INDEX_COMBINE
INDEX_DESC
INDEX_JOIN
INDEX_FFS
INDEX_SS
INDEX_SS_ASC
INDEX_SS_DESC
NO_INDEX
NO_INDEX_FFS
NO_INDEX_SS

2.3使用查询转换提示
查询转换提示对于数据仓库非常有帮助。FACT提示可以在查询中将表强制转换成FACT表或驱动表。NO_FACT提示正好相反。
当联接多个表时,STAR_TRANSFORMATION提示用于有效地访问事实表。如果某个模式的结构显示为数据仓库模式,但实际上并不是数据仓库,NO_STAR_TRANSFORMATION提示
就会指示优化器不执行星状查询转换。下面列出了各个查询转换提示:
FACT
MERGE
NO_EXPAND
NO_FACT
NO_MERGE
NO_QUERY_TRANSFORMATION
NO_REWRITE
NO_STAR_TRANSFORMATION
NO_UNNEST
REWRITE
STAR_TRANSFORMATION
UNNEST
USE_CONCAT

2.4使用连接操作提示
LEADING指定连接顺序首先使用的表,而ORDERED告诉优化器基于FROM子句中的表顺序连接这些表,并且使用第一个表作为驱动表(最先访问的表)。
其他指导使用连接操作的提示如下:
NO_USE_HASH
NO_USE_MERGE
NO_USE_NL
USE_HASH
USE_MERGE
USE_NL
USE_NL_WITH_INDEX

2.5使用并行执行
提示的并行执行组可以应用于使用并行选项的数据库。这些提示覆盖了表指定的并行度。
NO_PARALLEL
NO_PARALLEL_INDEX
PARALLEL
PARALLEL_INDEX
PQ_DISTRIBUTE

2.6其他提示
在不启用并行选项的情况下也可以使用APPEND和NOAPPEND提示,但它们经常与并行选项一起使用。缓存组保存了最近经常使用的(CACHE)或最近没有使用的(NOCACHE)一些
提示。类似于APPEND和CACHE,下面的提示可用于影响优化器处理表访问的方式:
APPEND
CACHE
CURSOR_SHARING_EXACT
DRIVING_SITE
DYNAMIC_SAMPLING
MODEL_MIN_ANALYSIS
NOAPPEND
NOCACHE
NO_PUSH_PRED
NO_PUSH_SUBQ
NO_PX_JOIN_FILTER
PUSH_PRED
PUSH_SUBQ
PX_JOIN_FILTER
QB_NAME

3.指定提示
如果没有用正确的方式指定提示,它就会成为注释并被忽略掉。
默认情况下,提示只影响它们显示在其中的代码块。如果提示在作为UNION操作一部分的查询中访问EMP表,则UNION中的其他查询不会受到该提示的影响。
可以在提示中指定查询块名,从而指定应用该提示的查询块。
使用QB_NAME提示指定查询块的名称。

4.指定多个提示
【技巧】可以用空格将多个提示分开。指定一些互相有冲突的提示会导致查询无法使用任何有冲突的提示。

5.使用别名时,提示别名而不是表名

6.使用提示
6.1使用FIRST_ROWS提示
FIRST_ROWS提示可以最快速度地检索第一行,指导优化器优化查询。
FIRST_ROWS提示一般会强制使用某些索引,而在正常的环境下可能不会使用这些索引。
在使用UPDATE和DELETE语句时可忽略FIRST_ROWS提示,这是因为查询的所有行都会被更新或删除。使用以下分组语句(GROUP BY、DISTINCT、INTERSECT、MINUS和
UNION)时也会忽略FIRST_ROWS提示。
还可以指定需要利用FIRST_ROWS来优化的行数,默认值是1。注意,这个值介于10-1000之间。这个使用FIRST_ROWS(n)的新方法是完全全基于成本的方法,它对n的值
相当敏感。如果所用的n值很小,基于成本的优化器(CBO)就会生成包括嵌套循环以及索引查找的计划。如果所用的n值很大,CBO会生成由散列连接和全表扫描组成的
计划(类似于ALL_ROWS)。
【技巧】FIRST_ROWS提示会使优化器选择可最快检索出查询第一行(或指定行)数据的路径,而代价就是检索很多行时速度将会非常慢。

6.2使用ALL_ROWS提示
select /*+all_rows*/ * from ...;
【技巧】ALL_ROWS提示会使优化器选择一条可最快检索所有查询行的路径,而代价就是在检索一行数据时,查询速度会非常慢。在系统参数文件中设置OPTIMIZER_MODE=ALL_ROWS
后,就可以将ALL_ROWS提示作为整个数据库的默认提示;查询级别的提示将重写特定查询的默认设置。

6.3 使用FULL提示
FULL提示可令查询重写优化器设置并对提示所指定的表进行全表扫描。
select /*+ FULL(table) */ column1,...
【技巧】FULL提示只对所指定的表而不是查询中的所有表进行全表扫描。FULL提示可以改善性能,这主要是因为它改变了查询中的驱动表,而不是因为全表扫描。

6.4 使用INDEX提示
select /*+index(table index1,index2) */ column1,..
【技巧】INDEX提示会使优化器选择提示中所指定的索引。每个表上有多个索引可以指定,但通常只需在给定查询中指定限制最多的索引(避免将每个索引的结果合并)。
如果已经指定多个索引,ORACLE将选择所指定的索引(一个或多个),因此在指定索引时一定要注意,否则提示可能会被重写。

select /*+index */ empno,ename,deptno
from emp
where deptno=1 and empno=7750;
【技巧】如果没有指定索引,INDEX提示将不会进行全表扫描,即使没有指定任何索引,优化器也会为这个查询选择最佳的索引。

6.5 使用NO_INDEX提示
NO_INDEX提示会禁止优化器使用指定的索引。这个提示在调整具有多个索引的查询时非常有用。
select /*+ no_index(table index1,index2...) */ column1, ...
select /*+ no_index(table index1) no_index(table index2) */ column1, ...
【技巧】NO_INDEX提示是性能调整专家的必备工具。利用它,优化器就无需考虑特定索引,这样在删除某个索引之前就可对其进行评估,或者对其他的索引
进行评估。注意不要与其他索引提示产生冲突。

6.6使用INDEX_JOIN 提示
INDEX_JOIN提示可以将同一个表的各个不同索引进行合并,这样只需要访问这些索引就行了,节省了重新检索表的时间。
select /*+index_join(table index1,index2...) */ column1,...
【技巧】INDEX_JOIN提示比使用索引并通过ROWID扫描整个表要快5倍。

--“附13.INDEX_JOIN效率比较”的小结
【小结】 select t.id,t.biz_date from scott.t_group1 t where t.biz_date='1111' and t.id=1600;
1.全表扫描的COST为5577
2.单索引访问(TABLE ACCESS BY INDEX ROWID的代价为索引代价的7倍)
|* 1 | TABLE ACCESS BY INDEX ROWID| T_GROUP1 cost: 22
|* 2 | INDEX RANGE SCAN | IDX_ID cost: 3
3.INDEX_JOIN(INDEX_JOIN的代价很小)
|* 1 | VIEW | index$_join$_001 |cost: 21
|* 2 | HASH JOIN
|* 3 | INDEX RANGE SCAN| IDX_ID |cost: 3
|* 4 | INDEX RANGE SCAN| IDX_BIZ_DATE |cost: 17
4.INDEX_JOIN的使用场景小结
1)每个索引的COST要远远小于全表扫描
2)执行连接的两个索引单独执行(INDEX ... SCAN)的COST要相近。只有这样才能使INDEX_JION的效率高于单个索引扫描后再通过ROWID访问表。

6.7使用INDEX_COMBINE提示
如果想让优化器使用指定的所有索引,INDEX_COMBINE提示可用来指定多个位图索引。还可以使用INDEX_COMBINE指定单个索引(对于指定位图索引,该提示优先于INDEX
提示)。对于B-树索引,可以使用INDEX提示而不是这个提示。
语法:
select /*+ index_combine(table index1,index2...) */ column1,...
【技巧】INDEX_COMBINE提示会使优化器合并表上的多个位图索引,而不是选择其中最好的索引(这是INDEX提示的用途)

6.8使用INDEX_ASC提示
语法:
select /*+ INDEX_ASC(table index1,index2) */ column1, ...
【技巧】从Oracle8i开始,INDEX_ASC提示与INDEX提示执行同样的功能,因为系统总是按照升序扫描索引。因为Oracle可以在将来改变这个默认值,所以该提示可一直确保
按照升序扫描索引。在Oracle9i中,降序索引是真正意义上按降序排列,Oracle将降序索引看作基于函数的索引。标为DESC的列将按照降序进行排序。

6.9使用INDEX_DESC提示
INDEX_DESC提示将按照降序(按照它们索引的值或顺序)扫描索引,这正好与INDEX和INDEX_ASC提示相反。当查询有多个表时,这个提示会被重写,因为索引需要按常规的升
序索引排列才可与查询中的其他表连接起来。该提示的一些限制包括它不能作用于位图索引或降序索引,这会按照升序扫描索引;该提示也不能跨越分区索引的边界进行操作,而
是对每个分区进行降序索引扫描。
语法:
select /*+ index_desc(table index1,index2..) */ column1,..

6.10使用INDEX_FFS提示
select /*+ INDEX_FFS(table index) */ column1,...

6.11使用ORDERED提示
【技巧】ORDERED提示是几个功能最强大的提示之一。它按照FROM子句中列出的先后顺序来处理查询中的表。许多变化都会改变这种运行方式:Oracle的版本、表中索引的存在与
否以及是否是已分析过表。当多表连接非常慢并且您不知道该做什么时,可以首先尝试使用ORDERED提示。
--RBO:在基于成本的优化以前,FROM子句中的最后一个表就是查询中的驱动表。

6.12使用LEADING提示
当查询的复杂程序增加时,我们就很难使用ORDERED提示来指出所有表的顺序。通常可以指出先访问哪一个表(驱动表),但不可能知道下面将访问哪一个表。
语法:
select /*+ leading(table1) */ column1,...
【技巧】LEADING提示类似于ORDERED提示。可以使用LEADING提示指定一个驱动查询的表,并让优化器判断下一个将访问的表。

6.13使用NO_EXPAND提示
NO_EXPAND提示可以保证优化器在评估以OR组合起的IN列表时不会陷入困境。它禁止优化器使用OR扩展。如果不使用NO_EXPAND提示,优化器将会产生很长的解释计划。
语法:
select /*+ no_expand */column1,...
示例:
select /*+ first_rows no_expand */ *
from scott.t_group1 t
where (t.id between 10 and 20
or (t.id between 100 and 250)
or (t.id between 170 and 780)
or (t.id between 200 and 610)
or (t.id between 230 and 740)
or (t.id between 300 and 800)
) ;
网上的例子:
扩展的意思就是:
比如你有 where cola='A' and colb in('B','C')如果你不加NO_EXPAND,
优化器会给你优化成这样where (cola='A' and colb='B') or (cola='A' and colb='C')然后运用索引查找数据
【小结】
1.没有找到合适的例子(测试时,NO_EXPAND没起做用)
2.扩展的目地是使用索引?
3.如查扩展后能使用索引,那么在某些场景扩展的效率应该更高。

6.14使用DRIVING_SITE提示
在提示中指定的表是用于处理实际连接的驱动站点。
语法:
 select /*+ DRIVING_SITE(table) */ column1,...
示例:
select /*+ DRIVING_SITE(deptremote) */ empno,ename,deptremote.deptno
from emp,dept@oratusc deptremote
where emp.deptno=deptremote.deptno
and deptremote.deptno=10
and empno=7747;
如果没有指定这个提示,Oracle通常会从远程站点检索行,并且将它们连接到本地站点中。因为empno=7747在很大程序上限制了查询,所以我们将emp表中的很少行发送到
远程站点上,而不是将整个dept表中的部门值发送回本地站点来处理。
还可以通过建立远程表的本地视图来限制从远程站点检索的行。本地视图应该有where 子句,从而视图可以在将行发送回本地数据库之前限制从过程数据库返回的行。RICH
就常常用这个方法来调整查询。
【技巧】DRIVING_SITE提示的功能非常强大,因为它可以限制通过网络处理的信息量。由DRIVING_SITE提示指定的表是处理连接所在的位置。在将记录返回给本地站点之前,
使用远程表的本地视图可以限制从远程站点传递的行数,从而改善性能。

6.15使用USE_MERGE提示
语法:
select /*+ use_merge(table) */ column1,...
也可以这样写:
select /*+ use_merge(table1,table2,...) */ column1,...
示例1:
select /*+ use_merge(a b c)*/*
from scott.emp a,scott.dept b,scott.dept_sort c
where a.deptno=b.deptno and b.deptno=c.deptno;

SQL> select /*+ use_merge(a b c)*/*
2 from scott.emp a,scott.dept b,scott.dept_sort c
3 where a.deptno=b.deptno and b.deptno=c.deptno;

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1552523850

--------------------------------------------------------------------------------
-------------------

| Id | Operation | Name | Rows | Bytes |TempSpc| Cost
(%CPU)| Time |

--------------------------------------------------------------------------------
-------------------

| 0 | SELECT STATEMENT | | 1 | 106 | | 74
4 (2)| 00:00:09 |

| 1 | MERGE JOIN | | 1 | 106 | | 74
4 (2)| 00:00:09 |

| 2 | MERGE JOIN | | 1 | 69 | | 26
5 (2)| 00:00:04 |

| 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 43105 | 1557K| | 26
1 (2)| 00:00:04 |

| 4 | INDEX FULL SCAN | IDX_DE | 43105 | | | 9
7 (2)| 00:00:02 |

|* 5 | SORT JOIN | | 14 | 448 | |
4 (25)| 00:00:01 |

| 6 | TABLE ACCESS FULL | EMP | 14 | 448 | |
3 (0)| 00:00:01 |

|* 7 | SORT JOIN | | 43105 | 1557K| 4776K| 47
9 (2)| 00:00:06 |

| 8 | TABLE ACCESS FULL | DEPT_SORT | 43105 | 1557K| | 5
5 (4)| 00:00:01 |

--------------------------------------------------------------------------------
-------------------


Predicate Information (identified by operation id):
---------------------------------------------------

5 - access("A"."DEPTNO"="B"."DEPTNO")
filter("A"."DEPTNO"="B"."DEPTNO")
7 - access("B"."DEPTNO"="C"."DEPTNO")
filter("B"."DEPTNO"="C"."DEPTNO")


Statistics
----------------------------------------------------------
924 recursive calls
6 db block gets
491 consistent gets
270 physical reads
0 redo size
2177 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
31 sorts (memory)
1 sorts (disk)
14 rows processed

示例2:
select /*+ use_merge( b c)*/*
from scott.emp a,scott.dept b,scott.dept_sort c
where a.deptno=b.deptno and b.deptno=c.deptno;

SQL> select /*+ use_merge( b c)*/*
2 from scott.emp a,scott.dept b,scott.dept_sort c
3 where a.deptno=b.deptno and b.deptno=c.deptno;

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 659543544

--------------------------------------------------------------------------------
----------

| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|
Time |

--------------------------------------------------------------------------------
----------

| 0 | SELECT STATEMENT | | 1 | 106 | | 571 (3)|
00:00:07 |

| 1 | MERGE JOIN | | 1 | 106 | | 571 (3)|
00:00:07 |

| 2 | SORT JOIN | | 1 | 69 | | 92 (5)|
00:00:02 |

|* 3 | HASH JOIN | | 1 | 69 | | 91 (4)|
00:00:02 |

| 4 | TABLE ACCESS FULL| EMP | 14 | 448 | | 3 (0)|
00:00:01 |

| 5 | TABLE ACCESS FULL| DEPT | 43105 | 1557K| | 87 (3)|
00:00:02 |

|* 6 | SORT JOIN | | 43105 | 1557K| 4776K| 479 (2)|
00:00:06 |

| 7 | TABLE ACCESS FULL | DEPT_SORT | 43105 | 1557K| | 55 (4)|
00:00:01 |

--------------------------------------------------------------------------------
----------


Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("A"."DEPTNO"="B"."DEPTNO")
6 - access("B"."DEPTNO"="C"."DEPTNO")
filter("B"."DEPTNO"="C"."DEPTNO")


Statistics
----------------------------------------------------------
4 recursive calls
6 db block gets
671 consistent gets
265 physical reads
0 redo size
2173 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
1 sorts (disk)
14 rows processed
6.16使用USE_NL提示
语法:
select /*+ use_nl(table1,table2,...) */ column1,...
【技巧】USE_NL提示通常可以为较小的结果集提供最快的响应时间(第一行返回最快),而USE_MERGE提示通常会在不可使用USE_HASH提示时提供最佳吞吐量。
NO_USE_NL提示优化器不使用嵌套循环连接。
USE_NL_WITH_INDEX采用两个参数--连接的内部表的名称和执行连接时使用的索引的名称。

6.17使用USE_HASH提示
USE_HASH提示可以很快地将来自多个表的行连接在一起,前提是您有该操作所需的足够内存。
语法:
select /*+ use_hash(table1,table2,...) */ column1,...
【技巧】USE_HASH提示通常可以为较大的结果集提供最佳的响应时间。

6.18使用PUSH_SUBQ提示
使用这个提示的最佳情况是当子查询只快速返回相对少的行时;这些行可用于充分限制外部查询中的行。
当使用合并连接或带有远程表的连接时,那就不能使用该提示。将子查询移到主查询部分中(如果可以的话)就可以很好地改善性能,特别是按正确的顺序驱动表时(先
访问原先的子查询)。
语法:
select /*+ push_subq */ column1,...
示例:
select /*+ push_subq */ emp.empno,emp.ename,itemno
from emp,orders
where emp.empno=orders.empno
and emp.deptno=
(select deptno from dept where loc='ELMONT');

6.19使用PARALLEL提示
PARALLEL提示会使优化器将需要执行全表扫描的查询分成多个部分(并行度)执行,然后在不同的操作系统进程中处理每个部分。
如果您为查询所设定的并行度为4,通常会为这个查询分配4个进程,如果需要排序,那就增加4个进程,另外还有一个将查询分离然后将每个部分组合在一起的进程。
一个度为4的查询真正应该有4+4+1个进程,也就是9个进程。
PARALLEL提示可以指定用于进行并行操作的并发服务器数量。这个提示还可应用于语句的INSERT、UPDATE、DELETE部分(您可以在使用提示后立即提交语句),也
可用于SELECT命令。另外,您应该在计划使用这个选项中创建一些带有PARALLEL子句的表。
语法:
/*+ parallel(table,degree) */
【技巧】(注:书中的这个技巧与下面的测试1结果不符)(参考测度2的结论)
使用PARALLEL提示可允许使用并行操作。如果没有在提示中指定度,那就会使用表创建时的默认值。

【测试1】在10.2.0.1测试
select /*+parallel(b) parallel(c)*/ *
from scott.dept b,scott.dept_sort c
where b.deptno=c.deptno;
alter table dept parallel 2;
alter table dept_sort parallel 2;
alter system set parallel_threads_per_cpu=8;
【测试1小结】测试发现,parallel提示的默认值不等于表的并行度,而是等于parallel_threads_per_cpu(也有可能是cpu_count*parallel_threads_per_cpu)。

【测试2】
alter table dept parallel 16;
alter table dept_sort parallel 16;
SQL> select *
2 from scott.dept b,scott.dept_sort c
3 where b.deptno=c.deptno;

43105 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 316312321

------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 43105 | 3115K| 10 (0)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | 43105 | 3115K| 10 (0)| 00:00:01 | Q1,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN BUFFERED | | 43105 | 3115K| 10 (0)| 00:00:01 | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | 43105 | 1557K| 6 (0)| 00:00:01 | Q1,02 | PCWP | |
| 5 | PX SEND HASH | :TQ10000 | 43105 | 1557K| 6 (0)| 00:00:01 | Q1,00 | P->P | HASH |
| 6 | PX BLOCK ITERATOR | | 43105 | 1557K| 6 (0)| 00:00:01 | Q1,00 | PCWC | |
| 7 | TABLE ACCESS FULL| DEPT | 43105 | 1557K| 6 (0)| 00:00:01 | Q1,00 | PCWP | |
| 8 | PX RECEIVE | | 43105 | 1557K| 4 (0)| 00:00:01 | Q1,02 | PCWP | |
| 9 | PX SEND HASH | :TQ10001 | 43105 | 1557K| 4 (0)| 00:00:01 | Q1,01 | P->P | HASH |
| 10 | PX BLOCK ITERATOR | | 43105 | 1557K| 4 (0)| 00:00:01 | Q1,01 | PCWC | |
| 11 | TABLE ACCESS FULL| DEPT_SORT | 43105 | 1557K| 4 (0)| 00:00:01 | Q1,01 | PCWP | |
------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - access("B"."DEPTNO"="C"."DEPTNO")


Statistics
----------------------------------------------------------
172 recursive calls
3 db block gets
890 consistent gets
932 physical reads
852 redo size
3065606 bytes sent via SQL*Net to client
31988 bytes received via SQL*Net from client
2875 SQL*Net roundtrips to/from client
5 sorts (memory)
0 sorts (disk)
43105 rows processed
【测试2小结】不使用PARALLEL提示时,ORACLE默认会使用表的并行度

【想法】跟据测试2的结论,可以使用alter table emp parallel 4;来调整并行度
1.指定并行度:alter table emp parallel 4;
2.查看表的并行度(默认是1):select degree from user_tables t where t.TABLE_NAME='EMP';
3.最好使用ALTER TABLE 修改并行度。这样当SQL从开发环境移植到生产环境后,优化并行度时不用修改SQL。
4.如果开发环境的I/O性能比较低,可以使用ALTER TABLE TABLENAME PARALLEL 1

6.20使用NO_PARALLEL提示
如果在建立表时已经设置了并行度,那么表在执行所有的全表扫描查询时都会使用已设置的度。
【提示】在标准化命名之前,NO_PARALLEL提示过去称为NOPARALLEL
语法:select /*+ no_parallel(table) */ ...
NO_PARALLEL提示产生并行度为1的查询。

6.21使用APPEND提示
语法:
insert /*+ append */ ...
【技巧】APPEND提示不会检查当前所用的块中是否有剩余空间,而直接将值插入到表中,它会直接将数据添加到新块中。
【其他】
append提示与nologging一起使用效率最高:
insert /*+append */ into ODS_LOANROUTEHISTORY NOLOGGING
select 。。。

6.22使用NOAPPEND提示
NOAPPEND提示用来重写PARALLEL插入操作的默认值(默认情况下是APPEND)。NOAPPEND提示与APPEND提示相反,它会在使用新块之前检查当前代码块中是否有
剩余空间。
语法:
insert /*+ noappend */ ...

6.23使用CACHE提示
CACHE提示会将全表扫描全部缓存(固定)到内存中,这样,访问同一个表的用户可直接在内存中查找数据,而不用到磁盘中进行查找。
语法:
select /*+ cache(table) */ column1,...
示例:
select /*+ FULL(dept) cache(dept) */ deptno,loc from dept;
整个DEPT表现在被缓存到内存中,并被标记为MRU(most recently used,最近使用的)对象。
【技巧】通常应该对用户经常访问的较小查找表使用CACHE提示(也可以在创建表时使用CACHE选项)。这样可以保证整个表都在内存中。

6.24使用NOCACHE提示
语法:
select /*+ nocache(table) */ column1,...
【技巧】NOCACHE提示可以用于禁止对已指定CACHE选项的表进行缓存。通常,在需要访问某个表但去再不需要缓存它的情况下可使用该提示。

6.25使用CLUSTER提示
语法:
select /*+cluster(table) */ column1,..
【技巧】CLUSTER提示会强制使用集群。如果经常访问连接表但却很少个修改它,那就最好使用集群。
【测试】通常不指定这个提示,优化器能做出正确的选择。
SQL> select * from scott.staff t ,scott.address_lines l
2 where t.sno=l.sno;

10000 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2430750019

---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10000 | 292K| 5981 (1)| 00:01:12 |
| 1 | NESTED LOOPS | | 10000 | 292K| 5981 (1)| 00:01:12 |
| 2 | TABLE ACCESS FULL | STAFF | 5000 | 70000 | 976 (1)| 00:00:12 |
|* 3 | TABLE ACCESS CLUSTER| ADDRESS_LINES | 2 | 32 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - filter("T"."SNO"="L"."SNO")

6.26使用HASH提示
语法:
select /*+ hash(table) */ column1,...

【测试】不使用提示优化器也能做出正确的选择
SQL> select * from scott.staff2 t where t.sno=100;
Execution Plan
----------------------------------------------------------
Plan hash value: 3460466525

----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 14 | 1 (0)| 00:00:01 |
|* 1 | TABLE ACCESS HASH| STAFF2 | 1 | 14 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("T"."SNO"=100)

6.27使用CURSOR_SHARING_EXACT提示
语法:
select /*+ cursor_sharing_exact */ column1,...
【技巧】CURSOR_SHARING_EXACT提示会将CURSOR_SHARING的系统参数文件设置改为FORCE或SIMILAR。

6.28使用QB_NAME提示--QB:QueryBlock?
QB_NAME提示用于将名称分配给语句中的查询块,然后可以在引用该查询块的语句中的其他某个位置分配一个提示。
示例:
select /*+ full(@empblock emp)*/*
from dept
where dept.deptno in
(select /*+ QB_NAME(EMPBLOCK)*/ emp.empno from emp);

7.其他一些提示和注意事项
1)INDEX_SS:(SKIP SCAN)指示优化器对特定的表使用索引的“跳跃式扫描”选项。
select /*+ index_ss(table index1,index2,..) */
2)INDEX_SS_ASC:升序的跳跃式扫描
3)INDEX_SS_DESC:降序的跳跃式扫描
4)opt_param:这是10gR2中的新提示,用于修改在查询执行期间有效的参数设置。
示例:
select /*+ opt_param('star_transformation_enabled','true') --如果参数值是数值,则不使用引号
5)USE_NL_WITH_INDEX:嵌套循环连接期间使用的索引
6)MODEL_MIN_ANALYSIS:指示优化器省略电子表格规则的一些编译时优化。该提示可以减少电子表格分析期间所需的编译时间,一般和SQL建模查询一起使用。
7)REWITE_OR_ERROR:如果查询没有重写,则查询中的REWRITE_OR_ERROR提示会产生如下的错误:“ORA-30393:a query block in the statement did not rewrite"。
【关于提示和存储纲要的注意事项】每次查询运行时,存储纲要允许查询使用预先确定的执行计划,无论该查询在何处运行。人们有时认为STORED OUTLINES是存储执行谋划
的位置,但实际情况并不是如此。相反,Oracle在数据库中存储一系列提示或指示,以精确的方式执行查询,从而重复在记录会话期间存储的执行计划。如果需要查询存储
纲要的提示,可以使用USER_OUTLINE_HINTS的如下查询:
select hint from user_outline_hints where name='your_outline_name';

8.使用提示可能遇到的问题
通常我们会发现提示并没有按照所需要的方式运行。有时优化器会重写提示,但通常会遇到如下所示的相关问题:
提示语法不正确
表没有经过分析
存在其他产生冲突的提示
提示需要正确设置某个系统参数
在查询中使用表的别名,但是在提示在使用的是表名而不是别名
提示需要使用不同版本的Oracle
您不了解这个提示的正确应用
因为上述的许多原因,您最近缺乏睡眠
软件故障

[@more@]

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/7901922/viewspace-1060016/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2013-02-03

  • 博文量
    53
  • 访问量
    36585