|
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
|
|