利用sqlprofile优化goldengate中慢的sql语句
HP unix中监控到一个进程占用cpu较高,后来发现是gg中的语句执行计划有问题,导致cpu偏高。由于gg中的语句不能更改,怎样才能改变不能更改的语句的执行计划呢,这里可以采用sqlprofile来优化。 [szggs1@szodsd01] $ top -h System: szodsd01 Wed Nov 5 10:17:16 2014 Load averages: 0.42, 0.47, 0.49 1007 processes: 599 sleeping, 408 running Cpu states: (avg) LOAD USER NICE SYS IDLE BLOCK SWAIT INTR SSYS 0.42 19.8% 0.0% 5.2% 75.0% 0.0% 0.0% 0.0% 0.0% System Page Size: 4Kbytes Memory: 40107992K (35984460K) real, 53292056K (48597616K) virtual, 12423080K free Page# 1/44 CPU TTY PID USERNAME PRI NI SIZE RES STATE TIME %WCPU %CPU COMMAND 3 ? 1697 oracle 178 20 25460M 6420K run 1780:54 95.10 94.93 oracleszodsd1 11 ? 28561 oracle 178 20 25461M 7236K sleep 55:06 8.01 8.00 oracleszodsd1 SQL> @getsql_spid Enter value for ospid: 1697 ADDR ---------------- C00000037A0351C8 SID_SERIAL SQL_ID_NUM P_NAME P_VALUE SQL_ID USERNAME PROGRAM EVENT STATUS BLOCKING_SESSION ---------- --------------- --------------- --------------- ------------- ---------- --------------- -------------------- -------- ---------------- 3152,32913 6khsffxsn05tg,0 driver id 1413697536 6khsffxsn05tg GGS replicat@szodsd SQL*Net message from ACTIVE #bytes 1 01 (TNS V1-V3) client 0 SQL_FULLTEXT -------------------------------------------------------------------------------- DELETE FROM "SPS_SZ"."TB_XX_XXXX_XXXX_XXX" WHERE "LOG_ID" = :b0 AND "PLAN_ID" = :b1 AND "LOG_NO" = :b2 AND "PLAN_RESULT" = :b3 AND "STAFF_CODE" = :b4 AND "WORK_ STAFF" = :b5 AND "OP_DATE" = :b6 AND "OP_TIME" = :b7 AND "LOG_NOTES" = :b8 AND " UNIT_ID" = :b9 AND ROWNUM = 1 --上面由replicat和GGS可见是gg的语句造成的 --查看gg中TB_XX_XXXX_XXXX_XXX对应的进程为RSZSPSE SQL> @getggmap Session altered. Enter value for ttable: TB_XX_XXXX_XXXX_XXX Enter value for towner: SPS_SZ STATS LOG_TIME PNAME SOURCE_OWNER SOURCE_TABLENAME TARGET_OWNER TARGET_TABLENAME GGS_OWNER ---------------------------------------- ------------------- --------------- -------------------- -------------------- -------------------- -------------------- ------------ stats RSZSPSE table *TB_XX_XXXX_XXXX_XXX 2014-11-05 00:00:18 RSZSPSE SPS_SZ_INST TB_XX_XXXX_XXXX_XXX SPS_SZ TB_XX_XXXX_XXXX_XXX szggs1 1 row selected. SQL> --果然延迟了很长时间,6个钟 GGSCI (szodsd01) 2> info RSZSPSE REPLICAT RSZSPSE Last Started 2014-11-01 14:00 Status RUNNING Checkpoint Lag 06:14:03 (updated 00:02:40 ago) Log Read Checkpoint File /odsd/szggs01/ggdata/sz/rszspsa/dirdat/si248293 2014-11-05 04:08:32.005523 RBA 1349428 --查看执行计划和outline信息,后面用sqlprofile优化 SQL> explain plan for 2 DELETE FROM "SPS_SZ"."TB_XX_XXXX_XXXX_XXX" 3 WHERE "LOG_ID" = :b0 4 AND "PLAN_ID" = :b1 5 AND "LOG_NO" = :b2 6 AND "PLAN_RESULT" = :b3 7 AND "STAFF_CODE" = :b4 8 AND "WORK_STAFF" = :b5 9 AND "OP_DATE" = :b6 10 AND "OP_TIME" = :b7 11 AND "LOG_NOTES" = :b8 12 AND "UNIT_ID" = :b9 13 AND ROWNUM = 1; Explained. SQL> @getplan 'general,outline,starts' Enter value for plan type:outline PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------------------- Plan hash value: 692294925 --------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------------------------- | 0 | DELETE STATEMENT | | 1 | 352 | 16760 (2)| 00:03:55 | | 1 | DELETE | TB_XX_XXXX_XXXX_XXX | | | | | |* 2 | COUNT STOPKEY | | | | | | |* 3 | TABLE ACCESS BY INDEX ROWID | TB_XX_XXXX_XXXX_XXX | 1 | 352 | 16760 (2)| 00:03:55 | | 4 | BITMAP CONVERSION TO ROWIDS | | | | | | | 5 | BITMAP AND | | | | | | | 6 | BITMAP CONVERSION FROM ROWIDS| | | | | | |* 7 | INDEX RANGE SCAN | IX_AA_AAA_AAAAAAA | 1757K| | 14 (79)| 00:00:01 | | 8 | BITMAP CONVERSION FROM ROWIDS| | | | | | |* 9 | INDEX RANGE SCAN | IX_AA_AAA_AAAAAAA_PLANID | 1757K| | 14 (79)| 00:00:01 | | 10 | BITMAP CONVERSION FROM ROWIDS| | | | | | |* 11 | INDEX RANGE SCAN | IX_BB_BBB_BBBB_BBBBBB | 1757K| | 2787 (1)| 00:00:40 | | 12 | BITMAP CONVERSION FROM ROWIDS| | | | | | |* 13 | INDEX RANGE SCAN | IX_CC_CCC_CCCC_CCCCCC | 1757K| | 13793 (1)| 00:03:14 | --------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - DEL$1 3 - DEL$1 / TB_XX_XXXX_XXXX_XXX@DEL$1 Outline Data ------------- /*+ BEGIN_OUTLINE_DATA BITMAP_TREE(@"DEL$1" "TB_XX_XXXX_XXXX_XXX"@"DEL$1" AND(("TB_XX_XXXX_XXXX_XXX"."LOG_ID") ("TB_XX_XXXX_XXXX_XXX"."PLAN_ID") ("TB_XX_XXXX_XXXX_XXX"."OP_DATE") ("TB_XX_XXXX_XXXX_XXX"."PLAN_RESULT"))) OUTLINE_LEAF(@"DEL$1") ALL_ROWS OPTIMIZER_FEATURES_ENABLE('10.2.0.4') IGNORE_OPTIM_EMBEDDED_HINTS END_OUTLINE_DATA */ Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(ROWNUM=1) 3 - filter("STAFF_CODE"=:B4 AND "WORK_STAFF"=:B5 AND "OP_TIME"=:B7 AND "LOG_NOTES"=:B8 AND "LOG_NO"=TO_NUMBER(:B2) AND "UNIT_ID"=TO_NUMBER(:B9)) 7 - access("LOG_ID"=TO_NUMBER(:B0)) 9 - access("PLAN_ID"=TO_NUMBER(:B1)) 11 - access("OP_DATE"=:B6) 13 - access("PLAN_RESULT"=TO_NUMBER(:B3)) Note ----- - dynamic sampling used for this statement --执行计划中一大堆的BITMAP关键字,很容易误以为这几个索引是bitmap索引,其实是普通索引来的。 --获取表和索引的相关信息 OWNER TABLE_NAME OBJECT_TYPE STA LAST_ANALYZED -------------------- ------------------------------ ------------ --- ------------------- SPS_SZ TB_XX_XXXX_XXXX_XXX TABLE --上表TB_XX_XXXX_XXXX_XXX统计信息过期 OWNER SEGMENT_NAME SEGMENT_TYPE Size(Mb) -------------------- ------------------------------ -------------------- ---------- SPS_SZ IX_CC_CCC_CCCC_CCCCCC INDEX 8434.625 SPS_SZ IX_AA_AAA_AAAAAAA INDEX 11176.625 SPS_SZ IX_AA_AAA_AAAAAAA_PLANID INDEX 11484.4375 SPS_SZ IX_BB_BBB_BBBB_BBBBBB INDEX 13138.5 SPS_SZ TB_XX_XXXX_XXXX_XXX TABLE 38322 --索引加起来都要比表大 OWNER INDEX_NAME TABLE_NAME PAR UNIQUENES DEGREE INDEX_TYPE LEAF_BLOCKS BLEVEL CLUSTERING_FACTOR % -------------------- ------------------------------ ------------------------------ --- --------- ---------- ---------- ----------- ---------- ----------------- ---------- SPS_SZ IX_AA_AAA_AAAAAAA TB_XX_XXXX_XXXX_XXX NO NONUNIQUE 1 NORMAL 284214 2 185996490 100 SPS_SZ IX_CC_CCC_CCCC_CCCCCC TB_XX_XXXX_XXXX_XXX NO NONUNIQUE 1 NORMAL 206567 2 6963531 .000006899 SPS_SZ IX_BB_BBB_BBBB_BBBBBB TB_XX_XXXX_XXXX_XXX NO NONUNIQUE 1 NORMAL 299483 2 6898441 .000049673 SPS_SZ IX_AA_AAA_AAAAAAA_PLANID TB_XX_XXXX_XXXX_XXX NO NONUNIQUE 1 NORMAL 284214 2 31263628 19.8460594 --由上可知,索引IX_AA_AAA_AAAAAAA的集群因子100,distinct_keys/NUM_ROWS*100=100,选择性非常好,类似于主键,基本返回1行。 --其他3个索引非常垃圾,完全可以不用。如果走4个索引的话,体积都大于全表扫描了,而且INDEX RANGE SCAN 是单块读,全表是多块读,还不如走全表了。 --由上面Outline Data信息里面得到如下信息: BITMAP_TREE(@"DEL$1" "TB_XX_XXXX_XXXX_XXX"@"DEL$1" AND(("TB_XX_XXXX_XXXX_XXX"."LOG_ID") ("TB_XX_XXXX_XXXX_XXX"."PLAN_ID") ("TB_XX_XXXX_XXXX_XXX"."OP_DATE") ("TB_XX_XXXX_XXXX_XXX"."PLAN_RESULT"))) --这里走bitmap肯定是错的,这里可以走索引IX_AA_AAA_AAAAAAA,但如何得到走IX_AA_AAA_AAAAAAA的hint呢? SQL> explain plan for 2 DELETE /*+index(a,IX_AA_AAA_AAAAAAA)*/ FROM "SPS_SZ"."TB_XX_XXXX_XXXX_XXX" a 3 WHERE "LOG_ID" = :b0 4 AND "PLAN_ID" = :b1 5 AND "LOG_NO" = :b2 6 AND "PLAN_RESULT" = :b3 7 AND "STAFF_CODE" = :b4 8 AND "WORK_STAFF" = :b5 9 AND "OP_DATE" = :b6 10 AND "OP_TIME" = :b7 11 AND "LOG_NOTES" = :b8 12 AND "UNIT_ID" = :b9 13 AND ROWNUM = 1; Explained. SQL> @getplan 'general,outline,starts' Enter value for plan type:outline PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------- Plan hash value: 2457304297 ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | DELETE STATEMENT | | 1 | 352 | 744K (1)| 02:53:43 | | 1 | DELETE | TB_XX_XXXX_XXXX_XXX| | | | | |* 2 | COUNT STOPKEY | | | | | | |* 3 | TABLE ACCESS BY INDEX ROWID| TB_XX_XXXX_XXXX_XXX| 1 | 352 | 744K (1)| 02:53:43 | |* 4 | INDEX RANGE SCAN | IX_AA_AAA_AAAAAAA | 1757K| | 14 (79)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - DEL$1 3 - DEL$1 / A@DEL$1 4 - DEL$1 / A@DEL$1 Outline Data ------------- /*+ BEGIN_OUTLINE_DATA INDEX_RS_ASC(@"DEL$1" "A"@"DEL$1" ("TB_XX_XXXX_XXXX_XXX"."LOG_ID")) --要用INDEX_RS_ASC这个hint,把A替换成表名就是了 OUTLINE_LEAF(@"DEL$1") ALL_ROWS OPTIMIZER_FEATURES_ENABLE('10.2.0.4') IGNORE_OPTIM_EMBEDDED_HINTS END_OUTLINE_DATA */ Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(ROWNUM=1) 3 - filter("STAFF_CODE"=:B4 AND "WORK_STAFF"=:B5 AND "OP_DATE"=:B6 AND "OP_TIME"=:B7 AND "LOG_NOTES"=:B8 AND "PLAN_ID"=TO_NUMBER(:B1) AND "LOG_NO"=TO_NUMBER(:B2) AND "PLAN_RESULT"=TO_NUMBER(:B3) AND "UNIT_ID"=TO_NUMBER(:B9)) 4 - access("LOG_ID"=TO_NUMBER(:B0)) Note ----- - dynamic sampling used for this statement --使用profile declare v_hints sys.sqlprof_attr; begin v_hints := sys.sqlprof_attr('INDEX_RS_ASC(@"DEL$1" "TB_XX_XXXX_XXXX_XXX"@"DEL$1" ("TB_XX_XXXX_XXXX_XXX"."LOG_ID"))'); dbms_sqltune.import_sql_profile('DELETE FROM "SPS_SZ"."TB_XX_XXXX_XXXX_XXX" WHERE "LOG_ID" = :b0 AND "PLAN_ID" = :b1 AND "LOG_NO" = :b2 AND "PLAN_RESULT" = :b3 AND "STAFF_CODE" = :b4 AND "WORK_STAFF" = :b5 AND "OP_DATE" = :b6 AND "OP_TIME" = :b7 AND "LOG_NOTES" = :b8 AND "UNIT_ID" = :b9 AND ROWNUM = 1', v_hints, 'SPS_SZ_TB_XX_XXXX_XXXX_XXX', force_match => true); end; / --验证执行计划是否只走IX_AA_AAA_AAAAAAA: SQL> explain plan for 2 DELETE FROM "SPS_SZ"."TB_XX_XXXX_XXXX_XXX" 3 WHERE "LOG_ID" = :b0 4 AND "PLAN_ID" = :b1 5 AND "LOG_NO" = :b2 6 AND "PLAN_RESULT" = :b3 7 AND "STAFF_CODE" = :b4 8 AND "WORK_STAFF" = :b5 9 AND "OP_DATE" = :b6 10 AND "OP_TIME" = :b7 11 AND "LOG_NOTES" = :b8 12 AND "UNIT_ID" = :b9 13 AND ROWNUM = 1; Explained. SQL> @getplan 'general,outline,starts' Enter value for plan type: PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------- Plan hash value: 2457304297 ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | DELETE STATEMENT | | 1 | 352 | 744K (1)| 02:53:43 | | 1 | DELETE | TB_XX_XXXX_XXXX_XXX | | | | | |* 2 | COUNT STOPKEY | | | | | | |* 3 | TABLE ACCESS BY INDEX ROWID| TB_XX_XXXX_XXXX_XXX | 1 | 352 | 744K (1)| 02:53:43 | |* 4 | INDEX RANGE SCAN | IX_AA_AAA_AAAAAAA | 1757K| | 14 (79)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(ROWNUM=1) 3 - filter("STAFF_CODE"=:B4 AND "WORK_STAFF"=:B5 AND "OP_DATE"=:B6 AND "OP_TIME"=:B7 AND "LOG_NOTES"=:B8 AND "PLAN_ID"=TO_NUMBER(:B1) AND "LOG_NO"=TO_NUMBER(:B2) AND "PLAN_RESULT"=TO_NUMBER(:B3) AND "UNIT_ID"=TO_NUMBER(:B9)) 4 - access("LOG_ID"=TO_NUMBER(:B0)) Note ----- - dynamic sampling used for this statement - SQL profile "SPS_SZ_TB_XX_XXXX_XXXX_XXX" used for this statement --执行计划对了。虽然纠正了执行计划,但毕竟索引IX_AA_AAA_AAAAAAA有11G,cpu还是有点偏高,扫描起来还是有点慢的,只有delete操作完了后才会降下来。但是现在效率上已经好很多了。 --相关的视图 SQL> select name,created from dba_sql_profiles order by created; NAME CREATED ------------------------------ ------------------- SPS_SZ_TB_XX_XXXX_XXXX_XXX 2014-11-05 10:49:58 5 rows selected. SQL> col attr_val for a80 SQL> select name,attr_val from dba_sql_profiles a, sys.sqlprof$attr b 2 where a.signature = b.signature 3 and a.name = 'SPS_SZ_TB_XX_XXXX_XXXX_XXX'; NAME ATTR_VAL ------------------------------ -------------------------------------------------------------------------------- SPS_SZ_TB_XX_XXXX_XXXX_XXX INDEX_RS_ASC(@"DEL$1" "TB_XX_XXXX_XXXX_XXX"@"DEL$1" ("TB_XX_XXXX_XXXX_XXX"."LOG_ID ")) 1 row selected. --@脚本 @getsql_spid set lines 200 pages 200 long 100000 col USERNAME for a10 col PROGRAM for a15 col EVENT for a20 col sid_serial for a10 col sql_id_num for a15 col p_name for a15 col p_value for a15 col addr new_value addr col sql_id new_value sql_id SELECT addr FROM gv$process c WHERE c.spid = &ospid; select a.sid ||','|| a.SERIAL# sid_serial, a.SQL_ID ||','|| a.sql_child_number sql_id_num, P1TEXT||chr(10)||P2TEXT||chr(10)||P3TEXT p_name, a.p1||chr(10)||a.p2||chr(10)||a.p3 p_value, decode(a.SQL_ID,null,a.PREV_SQL_ID,a.SQL_ID) sql_id, a.USERNAME, a.PROGRAM, a.EVENT, a.STATUS, a.BLOCKING_SESSION from gv$session a where a.PADDR = '&addr'; select c.SQL_FULLTEXT from gv$sqlarea c where c.SQL_ID='&sql_id'; cl col --@getplan set feedback off pro 'general,outline,starts' pro acc type prompt 'Enter value for plan type:' default 'general' select * from table(dbms_xplan.display) where '&&type'='general'; select * from table(dbms_xplan.display(null, null,'advanced -projection')) where '&&type'='outline'; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST')) where '&&type'='starts'; set feedback on undef type
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。