【Oracle中使用sta和hint进行性能优化】

最近工作中遇到一个非常诡异的事情: sql直接执行快,在存过/匿名块/视图里面执行慢。查看语句的执行计划一模一样,通过对SQL的逐步分析,发现是后台实际的SQL_ID不一致导致的。本文用于对记录对于问题的分析步骤,以及用到的一些优化方式。

一:优化思路:

1:确定SQL卡在那个部分。
将sql分解成一个个select,然后通过insert into test select……在直接执行和在declare匿名块中执行的时间进行比较。然后在plsqldev sessions里面定位卡住的sql,不断对语句进行拆解,最终确认慢的不能再拆的sql。
2:确定实际的执行计划
抓取实际的sql_id,sql_child_number,然后比较执行计划,通过hint,让慢的向快的靠拢;或者用sta进行优化。

--查询当前创建session的sid 及SERIAL#
select * From v$mystat
select * from v$session where sid=3968

--1,执行快的sql(多执行几次)
--2,执行慢的sql

--用上面的sid 及SERIAL#
create table gsc_test as
select * from v$active_session_history a where a.SESSION_ID=3968 and a.SESSION_SERIAL#='12485'

--找到快慢sql的sql_id和sql_child_number
select * from gsc_test 
order by 2 desc

--比较执行计划
select * from v$sqlarea where sql_id in ('4nuwpcuxtbmtz','9903hw5j2gyu7')
select * from table(dbms_xplan.display_cursor('4nuwpcuxtbmtz',0,'advanced'))
select * from table(dbms_xplan.display_cursor('9903hw5j2gyu7',0,'advanced'))

二:常规优化

1:查询执行计划,该用的索引是否使用到,执行计划是否合理。在多个表进行关联时关键的字段上需要有索引,而且字段类型需要一致,否者索引不会用的。注意执行的顺序,让更多的数据尽早的过滤掉。但索引并不是万能的,索引字段的值过于分散,如字典类的集中对于性能提升并没有太大的提升。
2:对于数据量很大的表查询,一般子查询的的效率很低,尽可能的合并到from后面。
3:使用with as关键字,这个关键字有个好处,可以吧多个表进行分开查询缓存,然后再一起计算,但是具体效果,得看实际情况。
4:更改缓存策略,将常用的表在CACHE中置顶。注意:只适合查询非常频繁而且数据量不太大的表。

三:sta 优化

SQL优化器(SQL Tuning Advisor STA)是Oracle10g中推出的帮助DBA优化工具,它主要用来优化复杂SQL的执行计划。该工具的使用方法调用dbms_sqltune包来完成。
Oracle 11g dbms_sqltune包官方文档

--举例
--这是需要被优化的SQL语句
select * From gsc_test;
--sql定位,找到实际执行的SQL_ID
select * from v$sqlarea where upper(sql_text) like '%gsc_test%'
--1,创建、执行优化任务
declare
   v_sqlid      varchar2(255) := '5xgrv9dr086jx'; --根据实际情况改一下
   v_taskname   varchar2(255);
begin
    v_taskname := 'query_for_'||v_sqlid;
   v_taskname := dbms_sqltune.create_tuning_task(sql_id     => v_sqlid,
                                                --time_limit  => 60,
                                                task_name   => v_taskname,
                                                description => v_sqlid);
    --执行创建好的优化任务                                          
   dbms_sqltune.execute_tuning_task(task_name => v_taskname);
   dbms_output.put_line('v_taskname='||v_taskname);
end;
/

--2,查看优化建议
select dbms_sqltune.report_tuning_task( 'query_for_5xgrv9dr086jx') from dual;
            
--3,接收优化建议,注意这段语句优化建议生成的,执行代表接受该优化建议
exec  dbms_sqltune.accept_sql_profile(task_name =>'query_for_5xgrv9dr086jx', task_owner => 'IRMQA2', replace =>TRUE, profile_type => DBMS_SQLTUNE.PX_PROFILE);


--4,查看优化的效果(注意,如果是jdbc连接池,那要重启应用才会生效)
select dbms_xplan.display_cursor('5xgrv9dr086jx') from dual

--确认某个sql是否在用profile
declare
   v_signature number;
   v_sql varchar2(4000) := '5xgrv9dr086jx';--sql 从v$sqlarea查询出来,去掉最后的空格
begin
   v_signature := dbms_sqltune.sqltext_to_signature(sql_text    => v_sql,
                                                    force_match => false);
   if v_signature is null then
      dbms_output.put_line('profile没有这个sql语句');
   else
      dbms_output.put_line('profile存在该语句');
   end if;
end;
/
  

--5,profile查看及删除
select * from user_advisor_log
select * from user_advisor_objects
select * from user_advisor_tasks

select * 
 from dba_sql_profiles 
where name='SYS_SQLPROF_01773daae3f00002'
   or upper(sql_text) like '%X009%'

begin
  dbms_sqltune.drop_sql_profile(name => 'SYS_SQLPROF_01773daae3f00002');
end;
/

四:hint优化

parallel

parallel用于为sql开启并行模式,类似java中的多线程。parallel对于大表的查询有显著的提升作用,但使用前注意查看CPU的负载情况。Oracle中有一个参数cpu_count,这个参数控制了数据库可以使用的CPU数量。还有一些其他的参数,可以在命令下面输入show parameter parallel命令进行查看。parallel_max_servers参数控制了最大并行数。
在这里插入图片描述

--语法:
/*+parallel(表名,并行数)*/
并行数一般需要小于cpu数量-1--实例
select /*+parallel(t1,6)*/ count(*) from gsc_test t;
full

full用于强制进行全表扫描,对于非常复杂的多表查询,一些数据量并不是很大的表使用全表扫描会有奇效,反而会减少实际开销。

/*+full(表名) full(表名) full(表名)*/
--实例
select /*+full(t1)*/ count(*) from gsc_test ;
rule

rule代表使用RBO优化器模式,这是一种Oracle已经废弃和不再支持的一个优化器模式,现在95%以上的系统都采用CBO 而不再采用RULE 的RBO。但是对于一些Oracle的内置视图查询会有奇效。

/*+ RULE */
--实例
select /*+ RULE */ count(*) from gsc_test ;

以上列举的的三个hint关键字是我常用的一些关键字,更多hint可以参考这一篇文章。ORACLE的HINT详解

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值