参数名称 | 参数值 | 参数说明 |
MEMORY_POOL | 80 | 避免频繁向系统申请内存 |
BUFFER | 100 | 总内存的50%,根据机器实际内存调整 |
BUFFER_POOLS | 1 | 减少数据缓存区冲突 |
MAX_BUFFER | 100 | 最大buffer大小,一般调整至机器内存的55%左右,根据机器实际内存调整 |
MAX_SESSIONS | 100 | 最大会话数 |
MAX_SESSION_STATEMENT | 100 | 回话允许打开最大句柄数 |
ENABLE_MONITOR | 2 | 动态监控,上线系统设置为0 |
COMPATIBLE_MODE | 2 | 兼容Oracle参数 |
PARALLEL_THRD_NUM | 10 | 多线程任务 |
MAX_OS_MEMORY | 95 | DM 服务器能使用的最大内存占操作系统物理内存与虚拟内存总和的百分比 |
MEMORY_TARGET | 0 | 共享内存池在扩充到此大小以上后,空闲时收缩回此指定大小,以 M 为单位 |
MEMORY_LEAK_CHECK | 0 | 所有内存池的泄漏检查 |
MEMORY_MAGIC_CHECK | 2 | 对所有内存池的校验 0 :不开启 |
FAST_POOL_PAGES | 3000 | 快速缓冲区页数 |
FAST_ROLL_PAGES | 1000 | 快速回滚缓冲区页数 |
RECYCLE_POOLS | 19 | RECYCLE 缓冲区分区数 |
MULTI_PAGE_GET_NUM | 1 | 缓冲区最多一次读取的页面数 |
SORT_BUF_SIZE | 2 | 排序缓存区最大值,以 M 为单位 |
HJ_BUF_GLOBAL_SIZE | 500 | HASH 连接操作符的数据总缓存大小>= HJ_BUF_SIZE ),系统级参数,以兆为单位。 |
HJ_BLK_SIZE | 1 | HASH 连接操作符每次分配缓存( BLK )以兆为单位,必须小于 HJ_BUF_SIZE 。 |
DICT_BUF_SIZE | 5 | 字典缓冲区大小,以兆为单位 |
N_MEM_POOLS | 1 | 内存池的数量 |
LIKE_OPT_FLAG | 7 | LIKE 查询的优化开关 |
VIEW_PULLUP_FLAG | 0 | 是否对视图进行上拉优化,把视图转换为其原始定义,消除视图 |
PARTIAL_JOIN_EVALUATION_FLAG | 1 | 是否对去除重复值操作的下层连接进行转换优化 |
USE_FK_REMOVE_TABLES_FLAG | 1 | 是否利用外键约束消除冗余表 |
SEL_ITEM_HTAB_FLAG | 0 | 当查询项中有相关子查询时,是否做 HTAB 优化。 |
CASE_WHEN_CVT_IFUN | 5 | 是否将 CASE WHEN THEN ELSE END 语句转换为 IFOPERATOR 函数 |
ORDER_BY_NULLS_FLAG | 0 | ASC 升序排序时,控制 NULL 值返回的位置。 |
CNNTB_OPT_FLAG | 0 | 是否使用优化的层次查询执行机制 |
ADAPTIVE_NPLN_FLAG | 3 | 是否启用自适应计划机制,仅OPTIMIZER_MODE=1 时生效。 |
VIEW_FILTER_MERGING | 2 | 是否对视图条件进行合并优化以及如何优化 |
CKPT_INTERVAL | 300 | 指定检查点的时间间隔。 |
EXPR_N_LEVEL | 200 | 表达式最大嵌套层数 |
CACHE_POOL_SIZE | 20 | SQL 缓冲池大小,以兆为单位 |
STAT_ALL | 0 | 在估算分区表行数时, 控制一些优化。 |
OPTIMIZER_AGGR_GROUPBY_ELIM | 1 | 当对派生视图进行分组查询,且分组项是派生视图分组项的子集时,是否考虑两层分组进行合并。 |
RLOG_PARALLEL_ENABLE | 0 | 是否启动并行日志 |
RLOG_APPEND_LOGIC | 0 | 是否启用在日志中记录逻辑操作的功能 |
UNDO_RETENTION | 90 | 事务提交后回滚页保持时间,单位为秒 |
SP_SET_PARA_VALUE(1,‘ENABLE_MONITOR’,1);
SP_SET_PARA_VALUE(1,‘MONITOR_TIME’,1);
复制
SF_SET_SESSION_PARA_VALUE(‘MONITOR_SQL_EXEC’,1);
复制
在使用ET工具前检查ENABLE_MONITOR,MONITOR_TIME是否开启,默认配置都是开启状态,我们再检查下MONITOR_SQL_EXEC,如果没有开启,在直接在要执行SQL的会话窗口先执行:
SF_SET_SESSION_PARA_VALUE(‘MONITOR_SQL_EXEC’,1);
复制
3.1.1 执行了此参数之后,执行我们要跟踪的SQL,点击执行号,就可以弹出分析了;
3.1.2 ET工具还可以分析存储过程,当存储过程执行比较慢的时候,我们调用后,也可以点击执行号,看他的执行占用备份比,我们通常是看PERCENT百分比,这个通常能代表,哪一个操作符耗时比较长。
用例:
3.1.3在DISQL中也可以使用
操作方法:ET(执行号);
select a.dxid from TEST_TAB1 a,TEST_TAB2 b
where a.dxid=b.dxid;
复制
SELECT * FROM v$cachepln WHERE SQLSTR LIKE ‘%TEST_TAB1%’;–140357593086048
复制
alter session set events ‘immediate trace name plndump level 140357593086048, dump_file ‘’/home/dmdba/140357593086048.log’‘’;
复制
set autotrace <OFF(默认值) | NL | INDEX | ON|TRACE> ;
复制
参数详解:
如上预估执行计划不准的情况下,我们需要的是服务器实际的执行计划,所以需要如下
设置SET AUTOTRACE TRACE来获取。
实操如下:当登录DISQL后
SQL> ALTER SESSION SET ‘MONITOR_SQL_EXEC’=1;
DMSQL 过程已成功完成
已用时间: 174.805(毫秒). 执行号:106510701.
SQL> set autotrace TRACE;
SQL> select a.dxid from TEST_TAB1 a,TEST_TAB2 b where a.dxid=b.dxid;
已用时间: 66.393(毫秒). 执行号:112458304.
SQL> select a.dxid from TEST_TAB1 a,TEST_TAB2 b where a.dxid=b.dxid;
行号 DXID
1 11487146
2 279528455
3 279659238
4 280097010
5 283571338
6 280439206
7 285447684
8 290622185
9 285435977
10 285435974
11 272522356
…
20 rows got
1 #NSET2: [2360, 2619310->0, 60]
2 #PRJT2: [2360, 2619310->0, 60]; exp_num(1), is_atom(FALSE)
3 #HASH2 INNER JOIN: [2360, 2619310->0, 60]; KEY_NUM(1);
4 #CSCN2: [1, 20, 30]; INDEX35162081(TEST_TAB2)
5 #CSCN2: [1469, 13228840->11668240, 30]; INDEX35162080(TEST_TAB1)
复制
说明:如上案例是服务器真实的执行计划。由于测试需要,制造SQL统计信息异常,预估执行计划可能是不准确的,但是实际set autotrace TRACE 后就是其真实服务器的执行计划,使用set autotrace TRACE后,我们可以看到带箭头的[2360, 2619310->0, 60][实际计划代价,结果,显示长度],而预估执行计划应该是这样显示[2360, 2619310, 60],和实际计划对比相差太远;预估计划结果2619310,实际是0,这就明显不对了,根据经验看,是未收集统计信息导致,收集后计划后,记录数就准确了。
Select
'sP_close_session('
||sess_id
||');' ,
datediff(ss, last_recv_time, sysdate) ss ,
cast(sf_get_session_sql(sess_id) as varchar) sql,
*
from
v$sessions
where
state='ACTIVE'
order by
last_send_time;
复制
说明:拼接了结束会话的sP_close_session,可以快速导出结束异常会话,如果时间无法获取则要v$dm_ini检查下ENABLE_MONITOR是否开启(1:打开;0:关闭),否则时间获取不到,就无法统计时间了;
4.2、SQL_INFO跟踪性能语句
通常存储过程慢SQL并不好抓取,在不是很好抓取的时候,我们可以采用性能分析工具里说的达梦DEBUG工具,但是有些无法调试的,我们怎么办呢?这个时候,我们可以改写待跟踪的存储过程,在把要跟踪的SQL嵌套到SQL_INFO中,这样有性能的SQL就可以写入日志表SQL_LOG了;实践中,改写存储过程需要有一定数据库开发能力的小伙伴来处理,我这里提供的是一种跟踪的性能方式;
--创建性能跟踪表
--DROP TABLE SQL_LOG;
CREATE TABLE SQL_LOG
(
GID VARCHAR2(100), --GUID
"USER_NAME" VARCHAR2(32) , --当前用户
"START_TIME" TIMESTAMP(0), --SQL开始执行时间
"END_TIME" TIMESTAMP(0) , --SQL执行结束时间
"SQL_TEXT" VARCHAR2(4000),--SQL执行语句
"ROW_COUNT" NUMBER(15) , --记录数
"LOG_TYPE" VARCHAR2(20) , --完成是SUCCESSFUL,报错是FAILED
"SESSION_ID" NUMBER(38, 0) , --会话ID
"LOG_DETAIL" VARCHAR2(2000), --错误信息
"INT_STACK" VARCHAR2(4000), ----堆栈信息
"SQL_TIMES" NUMBER(10, 2) --记录SQL执行时间
);
CREATE INDEX IND_SQL_LOG_SQLTEXT ON SQL_LOG(SQL_TEXT);
/
--创建跟踪过程
CREATE OR REPLACE PROCEDURE SQL_INFO("I_SQLSTART" IN VARCHAR2(32000))
AS
--说明:跟踪存储过程中某些慢SQL,跟踪大于0.1的SQL,根据场景可以改写
V_ROWCOUNT INT;
V_TIME DATE; --定义时间
V_ERRMSG VARCHAR2(5000); --获取异常记录
V_SQLTEXT VARCHAR2(32767); --获取传递的记录
V_SQLTEXT_INS VARCHAR2(9000); --SQL记录
V_CURTIME NUMBER(20,2); --开始时间
V_USETIME NUMBER(20,2); --使用时间
V_SESSION NUMBER(30); --SID记录
V_INT_STACK VARCHAR2(4000);
BEGIN
V_TIME:=SYSDATE;
V_CURTIME:=DBMS_UTILITY.GET_TIME;
V_SQLTEXT:=TRIM(I_SQLSTART);
WHILE INSTR(V_SQLTEXT,' ')>0 LOOP
V_SQLTEXT:=REPLACE(V_SQLTEXT,' ',' ');
END LOOP;
--执行主体EXECUTEIMMEDIATE
EXECUTE IMMEDIATE V_SQLTEXT;
V_ROWCOUNT:=SQL%ROWCOUNT;
V_USETIME:=(DBMS_UTILITY.GET_TIME-V_CURTIME)/100;
--这里调整多少秒的记录写入到SQL_LOG日志表中,这个可以嵌套到性能表里
IF V_USETIME>=0.1 THEN
V_SQLTEXT_INS:=TRIM(SUBSTRB(V_SQLTEXT,1,4000));--达梦单列VARCHAR2可以存储9000以上,如果SQL够长,我们可以改大些
V_SESSION:=SESSID;--会话SID
V_INT_STACK:=DBMS_UTILITY.FORMAT_CALL_STACK;
INSERT INTO SQL_LOG
(GID,USER_NAME,START_TIME,END_TIME,SQL_TEXT,ROW_COUNT,LOG_TYPE,SESSION_ID,INT_STACK,SQL_TIMES)
VALUES (GUID(),USER,V_TIME,SYSDATE,V_SQLTEXT_INS,V_ROWCOUNT,'SUCCESSFUL',V_SESSION,V_INT_STACK,V_USETIME);
END IF;
EXCEPTION
--如果SQL中执行异常,也会写SQL_LOG中,方便我们分析错误语句
WHEN OTHERS THEN
ROLLBACK;
V_ERRMSG:=SQLERRM(SQLCODE);
V_INT_STACK:=DBMS_UTILITY.FORMAT_CALL_STACK;
V_SQLTEXT_INS:=TRIM(SUBSTRB(I_SQLSTART,1,4000));--达梦VARCHAR2可以存储9000以上,如果SQL够长,我们可以改大些
V_USETIME:=(DBMS_UTILITY.GET_TIME-V_CURTIME)/100;
INSERT INTO SQL_LOG
(GID,USER_NAME,START_TIME,END_TIME,SQL_TEXT,LOG_TYPE,SESSION_ID,LOG_DETAIL,INT_STACK,SQL_TIMES)
VALUES (GUID(),USER,V_TIME,SYSDATE,V_SQLTEXT_INS,'FAILED',V_SESSION,V_ERRMSG,V_INT_STACK,V_USETIME);
COMMIT;
RAISE;
END SQL_INFO;
复制
BEGIN
–DEMO
SQL_INFO(‘CREATE TABLE FMISTMP.TEST_003 AS
SELECT * FROM DBA_OBJECTS’);
END;
复制
SELECT * FROM SQL_LOG WHERE SQL_TEXT LIKE ‘CREATE TABLE FMISTMP.TEST_003%’
复制
以上只是举例一个简单的创建备份表进行演示,实际上存储过程中很多动态拼接语句,都是可以放到SQL_INFO中,然后在执行过程中就可以跟踪到他的SQL是那一句慢了。
