当前所在位置: 主页 > 耀世新闻 > 公司新闻

Oracle Hints,Oracle并行模式(Parallel) 在SQL调优中的重要作用

?

2013年11月17日 12:59:24?雾里看花5566?阅读数:5422更多

个人分类:?数据库-oracle

谈谈HINT 在SQL调优中的重要作用!

在大表查询等操作中能够起到良好的效果,
基于并行查询要启动并行进程、分配任务与系统资源、合并结果集,这些都是比较消耗资源,
但我们为能够减少执行事务的时间使用parallel HINT还是值得的,尤其在ODS系统中报表统计等方面更有使用意义.
一般而言主要在如下情况使用parallel HINT
1.表的数据量很大,超过一千万;?
2.数据库主机是多个CPU;
3.系统的当前负载较低;

简单的测试如下,效果很明显的:

 
  1. ?
  2. ?
  3. ?
  4. ?
  5. ?
  6. ?
  7. ?
  8. ?
  9. ?
  10. ?
  11. ?
  12. ?
  13. ?
  14. ?
  15. ?

https://blog.csdn.net/u012354280/article/details/16369149

?

?

2017年09月06日 18:00:39?白开水Luis?阅读数:5815

1. 实例

(1)insert 加速

insert into dcustcomposmsg?
select * from dcustcomposmsg_new e;?
commit;

(2)select create加速
CREATE TABLE TEMP_DCUST_GRADE ?NOLOGGING PARALLEL 10 AS
? ? ? ? ? ? ? ? ? ?SELECT *
? ? ? ? ? ? ? ? ? ? FROM DCUST_BASIC_INFO_D PARTITION (P_'||V_TOLL_NO||') D?
? ? ? ? ? ? ? ? ? ?WHERE EXISTS(SELECT ''A'' FROM DCUSTHIGH PARTITION (P_'||V_REGION_CODE||') A
? ? ? ? ? ? ? ? ? ?WHERE D.ID_NO = A.ID_NO )

2. 用途

强行启用并行度来执行当前SQL。这个在Oracle 9i之后的版本可以使用,之前的版本现在没有环境进行测试。也就是说,加上这个说明,可以强行启用Oracle的多线程处理功能。举例的话,就像电脑装了多核的CPU,但大多情况下都不会完全多核同时启用(2核以上的比较明显),使用parallel说明,就会多核同时工作,来提高效率。

但本身启动这个功能,也是要消耗资源与性能的。所有,一般都会在返回记录数大于100万时使用,效果也会比较明显。

3. 语法


这个可以加到insert、delete、update、select的后面来使用(和rule的用法差不多,有机会再分享rule的用法)

开启parallel功能的语句是:

alter session enable parallel dml;

这个语句是DML语句哦,如果在程序中用,用execute的方法打开。

4. 实例说明

用ERP中的transaction来说明下吧。这个table记录了所有的transaction,而且每天数据量也算相对比较大的(根据企业自身业务量而定)。假设我们现在要查看对比去年一年当中每月的进、销情况,所以,一般都会写成:

select to_char(transaction_date,'yyyymm') txn_month,

sum(

? decode(

? sign(transaction_quantity),1,transaction_quantity,0
? )

? ) in_qty,

sum(

? decode(

? sign(transaction_quantity),-1,transaction_quantity,0
? )

? ) out_qty

? from mtl_material_transactions mmt

where transaction_date >= add_months(

? to_date(

? to_char(sysdate,'yyyy')||'0101','yyyymmdd'),

? -12)

and transaction_date <= add_months(

? to_date(

? to_char(sysdate,'yyyy')||'1231','yyyymmdd'),

? -12)

group by to_char(transaction_date,'yyyymm')?

这个SQL执行起来,如果transaction_date上面有加index的话,效率还算过的去;但如果没有加index的话,估计就会半个小时内都执行不出来。这是就可以在select 后面加上parallel说明。例如:
select
to_char(transaction_date,'yyyymm') txn_month,

...



这样的话,会大大提高执行效率。如果要将检索出来的结果insert到另一个表tmp_count_tab的话,也可以写成:
insert
? into tmp_count_tab

(

? txn_month,

? in_qty,

? out_qty

)

select
to_char(transaction_date,'yyyymm') txn_month,

...



插入的机制和检索机制差不多,所以,在insert后面加parallel也会加速的。关于insert机制,这里暂不说了。
Parallel后面的数字,越大,执行效率越高。不过,貌似跟server的配置还有oracle的配置有关,增大到一定值,效果就不明显了。所以,一般用8,10,12,16的比较常见。我试过用30,发现和16的效果一样。不过,数值越大,占用的资源也会相对增大的。如果是在一些package、function or procedure中写的话,还是不要写那么大,免得占用太多资源被DBA开K。


5. Parallel也可以用于多表

多表的话,就是在第一后面,加入其他的就可以了。具体写法如下:



6. 小结

关于执行效率,建议还是多按照index的方法来提高效果。Oracle有自带的explan road的方法,在执行之前,先看下执行计划路线,对写好的SQL tuned之后再执行。实在没办法了,再用parallel方法。Parallel比较邪恶,对开发者而言,不是好东西,会养成不好习惯,导致很多bad SQL不会暴漏,SQL Tuning的能力得不到提升。我有见过某些人create table后,从不create index或primary key,认为写SQL时加parallel就可以了。

?

?

https://blog.csdn.net/zhanglu0223/article/details/77869553

?

2011年12月23日 20:30:51?米菲的泰迪?阅读数:25940?标签:?oracletable优化parallelinsertmerge更多

个人分类:?Oracle

在向大家详细介绍Oracle Hints之前,首先让大家了解下Oracle Hints是什么,然后全面介绍Oracle Hints,希望对大家有用。基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担。但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比。


此时就需要DBA进行人为的干预,告诉优化器使用我们指定的存取路径或连接类型生成执行计划,从而使语句高效的运行。例如,如果我们认为对于一个特定的语句,执行全表扫描要比执行索引扫描更有效,则我们就可以指示优化器使用全表扫描。在Oracle中,是通过为语句添加 Hints(提示)来实现干预优化器优化的目的。


Oracle Hints是一种机制,用来告诉优化器按照我们的告诉它的方式生成执行计划。我们可以用Oracle Hints来实现:
1) 使用的优化器的类型
2) 基于代价的优化器的优化目标,是all_rows还是first_rows。
3) 表的访问路径,是全表扫描,还是索引扫描,还是直接利用rowid。
4) 表之间的连接类型
5) 表之间的连接顺序
6) 语句的并行程度


2、HINT可以基于以下规则产生作用
表连接的顺序、表连接的方法、访问路径、并行度


除了”RULE”提示外,一旦使用的别的提示,语句就会自动的改为使用CBO优化器,此时如果你的数据字典中没有统计数据,就会使用缺省的统计数据。所以建议大家如果使用CBO或Hints提示,则最好对表和索引进行定期的分析。


如何使用Hints:


Hints只应用在它们所在sql语句块(statement block,由select、insert、update、delete关键字标识)上,对其它SQL语句或语句的其它部分没有影响。如:对于使用union操作的2个 sql语句,如果只在一个sql语句上有Hints,则该Hints不会影响另一个sql语句。


我们可以使用注释(comment)来为一个语句添加Hints,一个语句块只能有一个注释,而且注释只能放在SELECT, UPDATE, or DELETE关键字的后面


使用Oracle Hints的语法:


{DELETE|INSERT|SELECT|UPDATE}

or

{DELETE|INSERT|SELECT|UPDATE} --+ hint [text] [hint[text]]...


注解:
1) DELETE、INSERT、SELECT和UPDATE是标识一个语句块开始的关键字,包含提示的注释只能出现在这些关键字的后面,否则提示无效。
2) “+”号表示该注释是一个Hints,该加号必须立即跟在”
  表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.
  例如:
  SELECT EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';?
  2.
  表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.
  例如:
  SELECT EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';
  3.
  表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;
  表明如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;
  例如:
  SELECT EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';
  4.
  表明对语句块选择基于规则的优化方法.
  例如:
  SELECT EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT';
  5.
  表明对表选择全局扫描的方法.
  例如:
  SELECT EMP_NO,EMP_NAM FROM BSEMPMS A WHERE EMP_NO='SCOTT';
  6.
  提示明确表明对指定表根据ROWID进行访问.
  例如:
  SELECT * FROM BSEMPMS WHERE ROWID>='AAAAAAAAAAAAAA'
  AND EMP_NO='SCOTT';
  7. ?
  提示明确表明对指定表选择簇扫描的访问方法,它只对簇对象有效.
  例如:
  SELECT BSEMPMS.EMP_NO,DPT_NO FROM BSEMPMS,BSDPTMS
  WHERE DPT_NO='TEC304' AND BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
  8.
  表明对表选择索引的扫描方法.
  例如:
  SELECT FROM BSEMPMS WHERE SEX='M';
  9.
  表明对表选择索引升序的扫描方法.
  例如:
  SELECT FROM BSEMPMS WHERE DPT_NO='SCOTT';
  10.
  为指定表选择位图访问路经,如果INDEX_COMBINE中没有提供作为参数的索引,将选择出位图索引的布尔组合方式.
  例如:
  SELECT * FROM BSEMPMS
  WHERE SAL<5000000 AND HIREDATE
  11.
  提示明确命令优化器使用索引作为访问路径.
  例如:
  SELECT SAL,HIREDATE
  FROM BSEMPMS WHERE SAL<60000;
  12.
  表明对表选择索引降序的扫描方法.
  例如:
  SELECT FROM BSEMPMS WHERE DPT_NO='SCOTT';
  13.
  对指定的表执行快速全索引扫描,而不是全表扫描的办法.
  例如:
  SELECT * FROM BSEMPMS WHERE DPT_NO='TEC305';
  14.
  提示明确进行执行规划的选择,将几个单列索引的扫描合起来.
  例如:
  SELECT * FROM BSEMPMS WHERE EMP_NO='SCOTT' AND DPT_NO='TDC306';
  15.
  对查询中的WHERE后面的OR条件进行转换为UNION ALL的组合查询.
  例如:
  SELECT * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';
  16.
  对于WHERE后面的OR 或者IN-LIST的查询语句,NO_EXPAND将阻止其基于优化器对其进行扩展.
  例如:
  SELECT * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';
  17.
  禁止对查询块的查询重写操作.
  18.
  可以将视图作为参数.
  19.
  能够对视图的各个查询进行相应的合并.
  例如:
  SELECT A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELET DPT_NO
  ,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO
  AND A.SAL>V.AVG_SAL;
  20.
  对于有可合并的视图不再合并.
  例如:
  SELECT A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELECT DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO AND A.SAL>V.AVG_SAL;
  21.
  根据表出现在FROM中的顺序,ORDERED使ORACLE依此顺序对其连接.
  例如:
  SELECT A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;
  22.
  将指定表与嵌套的连接的行源进行连接,并把指定表作为内部表.
  例如:
  SELECT BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
  23.
  将指定的表与其他行源通过合并排序连接方式连接起来.
  例如:
  SELECT * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
  24.
  将指定的表与其他行源通过哈希连接方式连接起来.
  例如:
  SELECT * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;
  25.
  强制与ORACLE所选择的位置不同的表进行查询执行.
  例如:
  SELECT * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;
  26.
  将指定的表作为连接次序中的首表.
  27.
  当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端
  例如:
  SELECT EMP_NAM FROM BSEMPMS;
  28.
  当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端
  例如:
  SELECT EMP_NAM FROM BSEMPMS;
  29.
  直接插入到表的最后,可以提高速度.
  insert into test1 select * from test4 ;
  30.
  通过在插入语句生存期内停止并行模式来启动常规插入.
  insert into test1 select * from test4 ;
?31. NO_INDEX: 指定不使用哪些索引





select * from emp where deptno=200 and sal>300;


32. parallel


select * from emp where deptno=200 and sal>300;


另:每个SELECT/INSERT/UPDATE/DELETE命令后只能有一个,但提示内容可以有多个,可以用逗号分开,空格也可以。


如:


---------
类似如下的一条语句:insert into xxxx select * from xxx a;数据量大约在75G左右,这位兄弟从上午跑到下午还没跑完,过来问我咋回事,说平常2hrs能跑完的东西跑了好几个小时还撒动静。查看系统性能也比较 正常,cpu,io都不繁忙,平均READ速度在80M/s左右(勉强凑合),但平均写速度只有10M不到。等待事件里面大量的‘ ‘PX Deq Credit: send blkd’,这里能看出并行出了问题,从而最后得知是并行用法有问题,修改之后20分钟完成了该操作。正确的做法应该是:
alter session enable dml parallel;


insert into xxxx select * from xxx a;


因为oracle默认并不会打开PDML,对DML语句必须手工启用。 另外不得不说的是,并行不是一个可扩展的特性,只有在数据仓库或作为DBA等少数人的工具在批量数据操作时利于充分利用资源,而在OLTP环境下使用并行 需要非常谨慎。事实上PDML还是有比较多的限制的,例如不支持触发器,引用约束,高级复制和分布式事务等特性,同时也会带来额外的空间占用,PDDL同 样是如此。有关Parallel excution可参考官方文档,在Thomas Kyte的新书《Expert Oracle Database architecture》也有精辟的讲述。
---------
select count(*)
From wid_serv_prod_mon_1100 a
?where a.acct_month = 201010
and a.partition_id = 10
and serv_state not in ('2HB', '2HL', '2HJ', '2HP', '2HF')
and online_flag in (0)
and incr_product_id in (2000020)
and product_id in (2020966, 2020972, 2100297, 2021116)
and billing_mode_id = 1
and exp_date > to_date('201010', 'yyyymm')
and not exists (select
? ? ? 1
? ? ? ?from wid_cdr_mon_1100 b
? ? ? where b.acct_month = 201010
? ? ? ? and b.ANA_EVENT_TYPE_4 in
? ? ? ? ? ? ('10201010201', '10202010201', '10203010201', '10203010202', '10203030201', '10203030202', '10204010201', '10204010202', '10204030201')
? ? ? ? and a.serv_id = b.serv_id)

?

https://blog.csdn.net/wb96a1007/article/details/7098687

?

?

?

2013年06月16日 00:11:41?luckman100?阅读数:3840更多

个人分类:?性能优化

之前我一直不理解为什么做并行DML之前要加上:alter session enable parallel dml,因为有一个假象蒙蔽了我:

下面的执行计划是没有执行alter session enable parallel dml产生的:

EXPLAIN PLAN FOR UPDATE test1 t SET object_id=1;

SELECT * FROM table (DBMS_XPLAN.display(NULL, NULL, 'BASIC +PARALLEL'));

当我看到执行计划里面有Q1,00这样的描述,就以为并行度hint生效了,但是我没注意到,这里并行度只用在对test1表的全盘扫描上,并没有用在update上!!!!!其实这还是远远不够的。下面是执行了alter session enable parallel dml产生的执行计划:

这里可以看到执行计划上的差别:这次不止全盘扫描时用到了并行度,而且update时也用上了并行度,这才是我们需要的!!

最后注意要把session的并行度关掉:alter session disable parallel dml

https://blog.csdn.net/luckyman100/article/details/9103853

?

?

[复制链接]

今天晴天了

论坛徽章:

5

2014年新春福章 日期:2014-02-18 16:49:31马上有钱 日期:2014-02-18 16:49:31优秀写手 日期:2014-10-28 06:00:14暖羊羊 日期:2015-03-04 14:54:572015年新春福章 日期:2015-03-06 11:59:47

电梯直达跳转到指定楼层

1#

?发表于 2014-3-27 08:26?|?只看该作者?回帖奖励

做了如下操作,测试没有 alter session enable parallel dml;情况下,parallel的hint是否能起作用?

SQL> show rel
Oracle?Database?11g?Enterprise Edition Release 11.2.0.3.0?


SQL> alter session set sql_trace = true;?

Session altered

SQL> insert into?big_table select * from big_table;

74516 rows inserted

SQL>?
SQL> insert into big_table select * from big_table;

149032 rows inserted

SQL> alter session set sql_trace = false;?

Session altered

找到trc文件,格式化后,看到如下:


insert into big_table select * from big_table


call? ?count? ? cpu? ? elapsed? ? disk? ?query? ? current? ?rows
------- -------------- ---------- ---------- ---------- --------------------
Parse? ?1? ?0.00? ? 0.01? ? 0? ? 1? ? 0? ?0
Execute? ?1? ?0.14? ? 0.23? ?792? ? 2492? ? 9667? ? 74516
Fetch? ?0? ?0.00? ? 0.00? ? 0? ? 0? ? 0? ?0
------- -------------- ---------- ---------- ---------- --------------------
total? ?2? ?0.14? ? 0.24? ?792? ? 2493? ? 9667? ? 74516

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 83
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)Row Source Operation
---------- ---------- -------------------------------------------------------------
? ?0? ? 0? ? 0LOAD TABLE CONVENTIONAL(cr=2519 pr=792 pw=0 time=242928 us)
? ?74516? ?74516? ?74516? ?TABLE ACCESS FULL?BIG_TABLE (cr=1066 pr=788 pw=0 time=29251 us cost=298 size=14507802 card=70086)

********************************************************************************

SQL ID: gujz6hynj50d6 Plan Hash: 4182993142

insert into big_table select * from big_table


call? ?count? ? cpu? ? elapsed? ? disk? ?query? ? current? ?rows
------- -------------- ---------- ---------- ---------- --------------------
Parse? ?1? ?0.00? ? 0.00? ? 0? ? 1? ? 0? ?0
Execute? ?1? ?0.23? ? 0.66? ? 0? ? 2939? ?19303? ?149032
Fetch? ?0? ?0.00? ? 0.00? ? 0? ? 0? ? 0? ?0
------- -------------- ---------- ---------- ---------- --------------------
total? ?2? ?0.23? ? 0.66? ? 0? ? 2940? ?19303? ?149032

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 83
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)Row Source Operation
---------- ---------- -------------------------------------------------------------
? ?0? ? 0? ? 0LOAD TABLE CONVENTIONAL(cr=2990 pr=0 pw=0 time=662873 us)
? ? 149032? ?149032? ?149032? ?PX COORDINATOR(cr=47 pr=0 pw=0 time=358870 us)
? ?0? ? 0? ? 0? ? PX SEND QC (RANDOM) :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=329 size=60410880 card=291840)
? ?0? ? 0? ? 0? ?PX BLOCK ITERATOR (cr=0 pr=0 pw=0 time=0 us cost=329 size=60410880 card=291840)
? ?0? ? 0? ? 0? ?TABLE ACCESS FULL BIG_TABLE (cr=0 pr=0 pw=0 time=0 us cost=329 size=60410880 card=291840)

********************************************************************************

SQL ID: 4yhdgar8gyhxy Plan Hash: 0


可以看到,虽然没有 alter session enable parallel dml, 但是 insert into big_table select * from big_table仍然走了并行,这和很多地方说的不一样,为什么呢?

?

http://www.itpub.net/thread-1852708-1-1.html

?

?

?

?


平台注册入口