https://www.cnblogs.com/lvcha001/p/13469500.html

接前序,本次场景中有索引,但是OGG复制进程使用了低效率的索引?  类似SQL使用低效索引,如何让Oracle使用好的索引,从而加快复制进程的效率呢?

疑问? Oracle为什么有好的索引,但是还是选择不好的索引,从而造成SQL效率低下,OGG复制进程缓慢呢?

本次DB版本11g,都是CBO,基于成本进行计算。

1.重新收集统计信息,让Oracle自动选择好的索引,走好的执行计划,从而让OGG复制进程同步速度加快;

2.可以使用绑定执行计划,因为生产环境中大表经常收集统计信息不靠谱,因此绑定执行计划的选择性更好。

根据基于Oracle的SQL优化一书中,绑定执行计划有三种情况:

1.使用SQL Profile手工进行绑定执行计划;

2.使用Oracle 11g后推出的SQL分析工具后,根据提示绑定执行计划;

3.使用Oracle 11g后推出的SQM 手工绑定执行计划。

一、收集统计信息,从而让SQL使用好的执行计划

1.1 OGG进程延迟,追踪定位慢SQL ,或者说定位OGG复制进程慢在什么地方。

查询进程延迟
ogg>info all
REPLICAT RUNNING R064 :: :: $ ps -ef|grep R064
oracle Jul31 ? :: /ogg/replicat PARAMFILE /ogg/dirprm/r064.prm REPORTFILE /ogg/dirrpt/R064.rpt PROCESSID R064
USESUBDIRS
$ ps -ef|grep
oracle Jul31 ? :: /ogg/replicat PARAMFILE /ogg/dirprm/r064.prm REPORTFILE /ogg/dirrpt/R064.rpt PROCESSID R064
USESUBDIRS
oracle Jul31 ? -:: oracxxx2 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq))) select s.sid,s.serial#,sql_id,p.program from v$process p,v$session s where p.addr=s.paddr and p.spid=;
SID SERIAL#
---------- ----------

检查是否存在异常event,阻塞等异常情况,null,基本说明是SQL执行效率问题。

select sql_id,SQL_PLAN_HASH_VALUE,event,BLOCKING_SESSION,CURRENT_OBJ#,count(*) from v$active_session_history where SAMPLE_TIME>sysdate-1 and SESSION_ID=2521 and SESSION_SERIAL#=7
group by sql_id,SQL_PLAN_HASH_VALUE,event,BLOCKING_SESSION,CURRENT_OBJ# order by 6,5;
2mgbv3kv27j1u 122754776 -1 1016
9gwf6964729pb 122754776 -1 1565
f5wzbp6ukpgyb 122754776 -1 19809
35a1j6rvxxq25 122754776 -1 24694
7hqzr0xnw1dzn 122754776 -1 32829

select sql_id,SQL_PLAN_HASH_VALUE,count(*) from v$active_session_history where SAMPLE_TIME>sysdate-1 and SESSION_ID=2521 and SESSION_SERIAL#=7
group by sql_id,SQL_PLAN_HASH_VALUE order by 3,1,2;

SQL_ID SQL_PLAN_HASH_VALUE COUNT(*)
------------- ------------------- ----------
9r3gsjgu643vc 1485047805 1
dhhn34zjdswwm 1485047805 2
51rz0rnxn6h63 1485047805 10
dmddfppkdjm3j 122754776  30
9qmjbmy368dt6 122754776 32
gxt936qxcskus 122754776 80
13cyznw9s3k22 122754776 82
7yf333kq4tsug 122754776 188
8ag1chwapa6g5 1485047805 197
cc22d5nz8us4n 1485047805 281
4ryk8q58djv4k 122754776 812
2mgbv3kv27j1u 122754776 1068
9gwf6964729pb 122754776 1640
f5wzbp6ukpgyb 122754776 20649
35a1j6rvxxq25 122754776 26210
7hqzr0xnw1dzn 122754776 34301       基本上就是这三个SQL导致这个OGG复制进程延迟很高,缓慢的问题。

检查SQL对应的SQL文本对象,及执行计划

select * from table(dbms_xplan.display_cursor('7hqzr0xnw1dzn'));
Plan hash value: 122754776
------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | | | 4 (100)| | | |
| 1 | DELETE | S_OTHER | | | | | | |
|* 2 | COUNT STOPKEY | | | | | | | |
| 3 | PARTITION RANGE SINGLE | | 1 | 150 | 4 (0)| 00:00:01 | KEY | KEY |
|* 4 | TABLE ACCESS BY LOCAL INDEX ROWID| S_OTHER | 1 | 150 | 4 (0)| 00:00:01 | KEY | KEY |
|* 5 | INDEX RANGE SCAN | IDX_S_OTHER_DATE | 1 | | 3 (0)| 00:00:01 | KEY | KEY |
------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM=1)
4 - filter(("TIME" IS NULL AND "TIME1"=:B1 AND "DATA1"=:B38 and ······
5 - access("STAT_DATE"=:B0 AND "STATTYPE"=:B5)

三条SQL涉及的对象一致,只是update or delete 少量差异,基本上都是一样的。可以发现SQL已经走了索引

1.2 检查SQL统计信息,对象涉及的索引及索引列的选择性。

--最消耗时间的执行计划步骤
select
inst_id,sql_plan_hash_value,sql_plan_line_id,
sql_plan_operation,sql_plan_options,event,
count(*) cnt
from gv$active_session_history
where sql_id='7hqzr0xnw1dzn' and
sample_time >sysdate-/
group by
inst_id,sql_plan_hash_value,sql_plan_line_id,
sql_plan_operation,sql_plan_options,event
order by count(*) ;
INST_ID SQL_PLAN_HASH_VALUE SQL_PLAN_LINE_ID SQL_PLAN_OPERATION SQL_PLAN_OPTIONS EVENT CNT
---------- ------------------- ---------------- ------------------------------ ------------------------------ -------------------- ----------
INDEX RANGE SCAN
TABLE ACCESS BY LOCAL INDEX ROWID 10194
慢在回表,说明SQL通过索引获取到非常多的ROWID,但是我们都知道SQL 文本最后有ROWNUM=1,因此可以说明SQL实际涉及一行记录,但是SQL通过索引访问获取到N条>>1条记录,索引选择性很差。

select owner,object_name,object_type from dba_objects where object_name='S_OTHER';
OWNER OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------------------------------
A S_OTHER TABLE PARTITION

select index_owner,index_name,table_name,column_name,column_position from dba_ind_columns where table_name='S_OTHER' order by index_name,column_position;

INDEX_OWNER INDEX_NAME COLUMN_NAME COLUMN_POSITION
------------------------------ ----------- -------
REP IDX_S_OTHER_DATE A_DATE 1
REP IDX_S_OTHER_DATE STYPE  2
REP IDX_S_OTHER_DATE S_DATE 1
REP IDX_S_OTHER_DATE STYPE1 2

可以发现,SQL选择的执行计划索引,对应有4个列

另一个索引是全列索引!!!  25个列,虽然有点。。。。不靠谱,但是根据rowunum=1的方式,我们可以认为这个索引等同于一个IOT表。因此实际的访问效率肯定是> 上面的慢索引。

select OWNER,TABLE_NAME,COLUMN_NAME,NUM_DISTINCT,NUM_NULLS,to_char(LAST_ANALYZED,'yyyy-mm-dd hh24') as "date" from dba_tab_col_statistics where table_name='S_ST_BUSI_OTHER' order by column_name;

可以发现统计信息都是19年2月份,慢索引的四个列,NUM_DISTINCT分别为 1200,700,2,3  因此组合索引效率并不高!!!

select segment_name,sum(bytes)/1024/1024/1024 from dba_segments where owner='REP' and segment_name='S_OTHER' group by segment_name;
SEGMENT_NAME SUM(BYTES)/1024/1024/1024
--------------------------------------------------------------------------------- -------------------------
S_OTHER 15.5256958

 

1.3 收集统计信息,观察执行计划

exec dbms_stats.gather_table_stats(ownname=>'R',tabname=>'S_OTHER',cascade=>true,degree=>,estimate_percent=>);
检查执行计划是否改变!!! 这里有个小细节,如果SQL执行效率很高,非常可能无法在cursor观察到。

select * from table(dbms_xplan.display_cursor('35a1j6rvxxq25'));

本次未看到执行计划改变!!!????  没效果???

通过ASH视图查询 SQL_ID 的执行计划。

--最消耗时间的执行计划步骤
select
inst_id,sql_plan_hash_value,sql_plan_line_id,
sql_plan_operation,sql_plan_options,event,
count(*) cnt
from gv$active_session_history
where sql_id='7hqzr0xnw1dzn' and
sample_time >sysdate-2/24
group by
inst_id,sql_plan_hash_value,sql_plan_line_id,
sql_plan_operation,sql_plan_options,event
order by count(*) ;

INST_ID SQL_PLAN_HASH_VALUE SQL_PLAN_LINE_ID SQL_PLAN_OPERATION SQL_PLAN_OPTIONS EVENT CNT
---------- ------------------- ---------------- ------------------------------ ------------------------------ -------------------- ----------
2 122754776 5 INDEX RANGE SCAN 4013
2 122754776 4 TABLE ACCESS BY LOCAL INDEX ROWID 10194

收集统计信息后

INST_ID SQL_PLAN_HASH_VALUE SQL_PLAN_LINE_ID SQL_PLAN_OPERATION SQL_PLAN_OPTIONS EVENT CNT
---------- ------------------- ---------------- ------------------------------ -------------

2 122754776 1 DELETE log file sync 4
2 122754776 0 DELETE STATEMENT 5
2 11252613 1 DELETE 6                             执行计划发生改变,并且cnt数量很低,说明效率很OK
2 122754776 1 DELETE 14
2 122754776 5 INDEX RANGE SCAN 3148
2 122754776 4 TABLE ACCESS BY LOCAL INDEX ROWID 8293

使用SQL脚本对比SQL执行效率,提升了4倍的访问效率。

二、绑定执行计划,从而让SQL使用好的执行计划

2.1 定位问题SQL,与上面套路一样

select sql_id,SQL_PLAN_HASH_VALUE,event,BLOCKING_SESSION,CURRENT_OBJ#,count(*) from v$active_session_history where SAMPLE_TIME>sysdate- 
and SESSION_ID= and SESSION_SERIAL#=
group by sql_id,SQL_PLAN_HASH_VALUE,event,BLOCKING_SESSION,CURRENT_OBJ# order by ,;
1wcqwzmn1mw6b 3794392338
观察执行计划 走  TABLE ACCESS BY LOCAL INDEX ROWID| S_DAY 索引。 与上面的例子类似,唯一不同的就是换了个用户,换了一个表名称。

2.2 绑定执行计划

.获得好的执行计划
由于SQL只有一个执行计划,并没有我们希望的走全列索引的执行计划。
因此第一步骤需要制造一个好的执行计划,可以使用explan
EXPLAIN PLAN FOR SELECT /* test_sql_20200828 */ * FROM T_USER where id= status= ......选择了4个好的列,及distinct较多的列,作为where条件 and rownum=;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
可以得到希望得到的执行计划。 .查询好的执行计划 sql_id, hash_plan
可以通过v$sql SQL_ID SQL_TEXT PLAN_HASH_VALUE 定位获得需要的信息。 这里有一个疑问???
假设我们explain plan for 的SQL条件是WHERE 4个列?
那么绑定执行计划后,走全列索引20个列,那么绑定后的执行计划中access 是4个列?filter 是其它条件20个列? 还是 access 是索引20个列,filter 是表中不包含索引列的信息。 这个疑问代表如果假设Oracle绑定后,access 选择4个列,说明Oracle是一个错误的执行计划,那样filter 需要排除16个列,甚至20个列,SQL效率低下;
如果假设access 选择4个列,filter rownum= 没有其它条件,严格与绑定的模板或者说好的执行计划步骤走,甚至得到的结果都可以理解为错误的??? 条件变少了!!!
有兴趣的朋友可以测试下,不在啰嗦。 测试结果为access索引全列+ filter rownum=,因此oracle 还是很聪明的。

2.3 固定执行计划

--绑定执行计划

declare
m_clob clob;
begin
select sql_fullteXt
into m_clob
from v$sql
where sql_id = '6up8w69qu5y98' --慢SQL需要优化的SQL_id
and child_number = ;
dbms_output.put_line(m_clob);
dbms_output.put_line(dbms_spm.load_plans_from_cursor_cache(sql_id => '6up8w69qu5666', --选择好的执行计划对应的SQL_ID,可以不一样
plan_hash_value => , --选择好的执行计划对应的plan_value
sql_text => m_clob,
fixed => 'YES',
enabled => 'YES')); end;
/

==如下可以查询绑定执行计划后的信息,如果有问题可以参考如下删除。
SELECT SQL_HANDLE,PLAN_NAME,ORIGIN FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%WF_H_WorkItem%';
SQL_HANDLE PLAN_NAME ORIGIN
------------------------------------------------------------
SQL_6e591e5940320852 SQL_PLAN_6wq8yb503422k0e58574a MANUAL-LOAD
VAR TEMP NUMBER;
BEGIN
:TEMP:=DBMS_SPM.DROP_SQL_PLAN_BASELINE(SQL_HANDLE=>'SQL_6e591e5940320852',PLAN_NAME=>NULL);
END;
/
SQL> SELECT SQL_HANDLE,PLAN_NAME,ORIGIN FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%WF_H_WorkItem%';
no rows selected

2.4 如何让SQL重新硬解析我们经常可以发现,绑定执行计划或者收集统计信息后。 SQL执行计划不变???

.Oracle默认收集统计信息,是oracle自行判断,什么时候让SQL原有的执行计划失效,从而后续涉及的对象下一次SQL执行硬解析;
.那我们如何手工让SQL 硬解析呢??? 前提条件,执行慢的SQL需要暂停执行,我们能改变的是新的SQL,而非现有正在执行慢的SQL;
OGG需要stop 涉及的进程。 .对对象进行DDL操作
举例说明
alter table a modify status varchar2(); 表字段长度更新(慎重)
表别名,列别名修改。 可以使用plsql修改建议 -- 设置表别名
COMMENT ON TABLE EMPLOYEE is '雇员';
--设置字段别名
COMMENT ON COLUMN PRODUCT.PRODUCT_CLASS_ID IS '产品分类代码';
参考http://blog.itpub.net/106943/viewspace-1005783/ 别名修改,比较好用,plsql改下就行,业务高峰期不要操作。 .清空sql涉及的共享池 参考
https://zm.sm-tc.cn/?src=l4uLj4zF0NCIiIjRk5aRioeWm5zRnJCS0LOWkYqH0M3PzsjSz8zQzsvOysbH0ZeLkg%3D%3D&uid=06b807ecd1b8ae1f4a368a691fabd3eb&hid=
305572c2dd05de2fc54a7211940a4021&pos=1&cid=9&time=1597929982090&from=click&restype=1&pagetype=0000804000000402&bu=ss_doc&query=Oracle%E6%B8%85%E7
%A9%BAsql+%E5%AF%B9%E5%BA%94%E7%9A%84shared+pool.%E5%9C%B0%E5%9D%80&mode=&v=1&province=%E5%A4%A9%E6%B4%A5%E5%B8%82&city=%E5%A4%A9%E6%B4%A5%E5%B8%8
2&uc_param_str=dnntnwvepffrgibijbprsvdsdichei zx@MYDB>select sql_text,sql_id,version_count,executions,OBJECT_STATUS,address,hash_value from v$sqlarea where sql_text like 'select object_name
from s%';
SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS OBJECT_STATUS ADDRESS HASH_VALUE
------------------------------------------------------------ --------------------------------------- ------------- ---------- ---------------
select object_name from s1 where object_id= 1s45nwjtws2tj VALID 00000000B4F85A18
select object_name from s1 where object_id= 1hdyqyxhtavqs VALID 00000000BE7E56C8 现在要删除object_id=20对应的SQL缓存的执行计划和解析树。 zx@MYDB>exec sys.dbms_shared_pool.purge('00000000B4F85A18,1942752049','C');
PL/SQL procedure successfully completed.
zx@MYDB>select sql_text,sql_id,version_count,executions,OBJECT_STATUS,address,hash_value from v$sqlarea where sql_text
like 'select object_name from s%';
SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS OBJECT_STATUS ADDRESS HASH_VALUE
------------------------------------------------------------ --------------------------------------- ------------- ---------- ------
select object_name from s1 where object_id= 1hdyqyxhtavqs VALID 00000000BE7E56C8 从输出可以看出object_id=20对应的SQL缓存的执行计划和解析树被删除了,而object_id=30对应的SQL的执行计划没有受影响。 需要注意的是,如果在10.2.0.4中使用dbms_shared_pool.purge,则在使用之前必须特工设置event (alter session set events '5614566 trace
name context forever'),否则dbms_shared_pool.purge将不起作用,这个限制在10.2.0.4以上的版本中已经不存在了。
如果默认没有安装dbms_shared_pool包的可以执行@?/rdbms/admin/dbmspool.sql .收集统计信息的时候使用参数
exec dbms_stats.gather_index_stats(ownname=>'R',indname=>'IDX_DATE',degree=>,estimate_percent=>,no_invalidate=>false);
由于收集表及索引统计信息时间太长,因此可以选择收集你想要的的索引单个统计信息。使用参数也是可以的。 如果只是为了加快时间,可以考虑,estimate_percent 采样比例使用0. 之类很小的值,应该是秒级别。 目的可以快速让对象涉及的SQL都硬解析,但是不好的地方在于,
oracle收集统计信息后会更新对象统计信息值,使用过低的比例,值不准确,可能影响其他的SQL。 但是如果SQL基本都是绑定执行计划可以忽略。

OGG复制进程延迟高,优化方法二(存在索引),SQL选择不好的索引的更多相关文章

  1. OGG复制进程延迟高,优化方法一(使用索引)

    日常运维过程中,可能发现OGG同步进程延迟很高: 本篇介绍其中的一种方式. OGG复制进程,或者说同步进程及通过解析ogg trail文件,输出dml语句,在目标库执行dml操作,那么延迟高可能性其一 ...

  2. OGG复制进程延迟不断增长

    1.注意通过进程查找sql_id时,进程号要查询两次 2.杀进程的连接 https://www.cnblogs.com/kerrycode/p/4034231.html 参考资料 1.https:// ...

  3. MySQL性能优化方法二:表结构优化

    原文链接:http://isky000.com/database/mysql-perfornamce-tuning-schema 很多人都将 数据库设计范式 作为数据库表结构设计“圣经”,认为只要按照 ...

  4. 【译】索引进阶(十二):SQL SERVER中的索引碎片【中篇】

    原文链接:传送门. 为了讨论碎片产生的原因,以及避免和移除索引碎片的技术,我们必须从本进阶系列后续将介绍的两个章节借用一些知识点:创建/更新索引的知识,以及向一个索引表插入数据行的相关知识. 当我们讲 ...

  5. Java Web 前端高性能优化(二)

    一.上文回顾 上回我们主要从图片的合并.压缩等方面介绍前端性能优化问题(详见Java Web 前端高性能优化(一)) 本次我们主要从图像BASE64 编码.GZIP压缩.懒加载与预加载以及 OneAP ...

  6. OGG复制同步,提示字段长度不够ORA-01704

    日常运维OGG的环境中,如果遇到复制进程报错,提示字段长度不足如何处理??? 正常情况下,字段长度不足,但是未达到Oracle的限制时,可以对字段进行扩大限制满足目的. 实际环境中,遇到源端GBK,目 ...

  7. OGG投递进程报错无法open文件,无法正常投递

    1.1现象 之前有个客户遇到一个问题,OGG同步数据链路,突然有一天网络出现问题,导致OGG投递进程无法正常投递,无法写入目标端的该文件. 猜测是由于网络丢包等原因导致文件损坏,无法正常open,re ...

  8. Oracle SQL语句性能优化方法大全

    Oracle SQL语句性能优化方法大全 下面列举一些工作中常常会碰到的Oracle的SQL语句优化方法: 1.SQL语句尽量用大写的: 因为oracle总是先解析SQL语句,把小写的字母转换成大写的 ...

  9. SQL语句优化方法30例

    1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化. 例如: SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_I ...

随机推荐

  1. 完了!TCP出了大事!

    前情回顾:<非中间人就不能劫持TCP了吗?> 不速之客 夜黑风高,乌云蔽月. 两位不速之客,身着黑衣,一高一矮,潜入Linux帝国. 这一潜就是一个多月,直到他们收到了一条消息······ ...

  2. zabbix监控4.4升级至5.0

    1. ZABBIX备份 [root@iZ2zeapnvuohe8p14289u6Z /]# mkdir -p /soft/zabbixback/zabbix-backup [root@iZ2zeapn ...

  3. git原理及如何选择分支模式

    一.git 原理介绍 1.git的四个工作区域 Git有四个工作区域:工作目录(Working Directory).暂存区(Stage/Index).资源库(Repository或Git Direc ...

  4. 获取判断IE版本 TypeError: Cannot read property 'msie' of undefined

    注意:以下方法只适用于IE11 以下: TypeError: Cannot read property 'msie' of undefined jquery1.9去掉了 $.browser  所以报错 ...

  5. 【FZYZOJ】细菌 题解(最短路)

    题目描述 为了研究一种新型细菌(称它为S型细菌)的性质,Q博士将S型细菌放在了一个犹如迷宫一般的通道面前,迷宫中N个站点,每个站点之间以一种单向通道的形式连接,当然,也有可能某两个站点之间是互不联通的 ...

  6. Python入门看这些,最详细学习书籍推荐

    随着人工智能以及脚本开发火热,Python已经被推上一个非常火热的巅峰! 那么,想要学习Python却又不知道从哪里开始的朋友,看这里呀~ Python在整个编程语言来说,是比较容易上手,而且“见效” ...

  7. 曲线生成与求交—Bezier曲线

    Bezier曲线生成 法国工程师Pierre Bezier在雷诺公司使用该方法来设计汽车.一条Bezier曲线可以拟合任何数目的控制点. 公式 设\(n+1\)个控制点\(P_0,P_1--P_n\) ...

  8. 敏捷工具:Scrum板与Kanban如何抉择?敏捷工具:Scrum板与Kanban如何抉择?

    Scrum板作为一种工具,主要应用于Scrum团队的敏捷项目管理,能够帮助团队更新任务进度,促进团队信息共享,及时发现任务过程中的异常现象,从而查漏补缺.团队在每日站会时会通过Scrum板来直观地展示 ...

  9. Windows下制作软件安装包

    一.下载 首先,下载SetupFactory9.0.3.0Trial(下载链接:https://www.haolizi.net/example/view_65380.html) 下载好会有一个压缩包 ...

  10. docker找回构建时被删除的文件

    设想这样一个场景:当一个docker镜像被多次引用构建,在某次构建中某个文件被删除,如何找回被删除的文件? 要想回答这么一个问题,首先得熟悉下docker镜像的分层存储结构,镜像每一层都是只读的: 那 ...