# 达梦数据库# 介绍达梦数据库管理系统(DM)是一款功能强大的关系型数据库管理系统,提供了丰富的功能和工具,使得数据管理变得更加高效和便捷。本文将介绍如何使用达梦数据库进行数据管理的基本步骤。
# 达梦数据库常用命令查看达梦数据库配置文件的相关参数 select * from v$dm_iniREAD ONLY 只读,不能修改SYS 系统级别,可以修改全局生效 IN FILE 只能在配置文件中修改SESSION 会话级别只有session 和 sys 类型可以在线更改, 其他类型更改需要重启
在线修改 dm_ini 内容 alter system set 'MEMORY_LEAK_CHECK' = 1 ; 或者 SP_SET_PARA_VALUE( 1 , 'MEMORY_LEAK_CHECK' , 1 ) ; alter session set 'MONITOR_SQL_EXEC' = 1 ; 或者 SF_SET_SESSION_PARA_VALUE( 'MONITOR_SQL_EXEC' , 1 ) ;
查询会话数和会话信息 select A. SESS_ID, A. SQL_TEXT, A. STATE, A. N_USED_STMT, A. CURR_SCH, A. USER_NAME, A. TRX_ID, A. CREATE_TIME, A. CLNT_TYPE, A. TIME_ZONE, A. OSNAME, A. CONN_TYPE, B. PROTOCOL_TYPE, B. IP_ADDR FROM SYS. V$SESSIONS A, SYS. V$CONNECT B where A. Sess_id= B. SADDR ORDER BY SF_GET_EP_SEQNO( A. rowid) , A. Sess_id; select SF_GET_SESSION_SQL( ASESS_ID) , A. SQL_TEXT, A. STATE, A. N_USED_STMT, A. CURR_SCH, A. USER_NAME, A. TRX_ID, A. CREATE_TIME, A. CLNT_TYPE, A. TIME_ZONE, A. OSNAME, A. CONN_TYPE, B. PROTOCOL_TYPE, B. IP_ADDR FROM SYS. V$SESSIONS A, SYS. V$CONNECT B where A. Sess_id= B. SADDR ORDER BY SF_GET_EP_SEQNO( A. rowid) , A. Sess_id; SELECT * FROM ( SELECT sess_id, sql_text, datediff ( ss, last_recv_time, SYSDATE) Y_EXETIME, SF_GET_SESSION_SQL ( SESS_ID) fullsql, clnt_ip FROM V$SESSIONS WHERE STATE = 'ACTIVE' ) WHERE Y_EXETIME >= 2 ; select count ( * ) from v$sessions; select count ( * ) from v$sessions where state= 'ACTIVE' ; select count ( * ) from v$sessions where state= 'IDLE' ; sp_close_session( sess_id) ;
慢 sql 和阻塞监控 SELECT DS. SESS_ID "被阻塞的会话ID" , DS. SQL_TEXT "被阻塞的SQL" , DS. TRX_ID "被阻塞的事务ID" , ( CASE L. LTYPE WHEN 'OBJECT' THEN '对象锁' WHEN 'TID' THEN '事务锁' END CASE ) "被阻塞的锁类型" , DS. CREATE_TIME "开始阻塞时间" , SS. SESS_ID "占用锁的会话ID" , SS. SQL_TEXT "占用锁的SQL" , SS. CLNT_IP "占用锁的IP" , L. TID "占用锁的事务ID" FROM V$LOCK L LEFT JOIN V$SESSIONS DSON DS. TRX_ID = L. TRX_ID LEFT JOIN V$SESSIONS SSON SS. TRX_ID = L. TID WHERE L. BLOCKED = 1 上述 SQL 语句中,“占用锁的会话 ID ”表示该会话占用这个对象的锁,且事务一直没有提交。导致“被阻塞的会话 ID ”无法对该对象上锁。可以参考以下解决方式: 方式一:杀掉占用锁的会话,释放锁。 SP_CLOSE_SESSION ( 占用锁的会话 ID ) ; 方式二:杀掉被阻塞的会话。 SP_CLOSE_SESSION ( 被阻塞的会话 ID ) ; WITH LOCKS AS ( SELECT O. NAME, L. * , S. SESS_ID, S. SQL_TEXT, S. CLNT_IP, S. LAST_SEND_TIME FROM V$LOCK L, SYSOBJECTS O, V$SESSIONS S WHERE L. TABLE_ID = O. ID AND L. TRX_ID = S. TRX_ID) , LOCK_TR AS ( SELECT TRX_ID WT_TRXID, TID BLK_TRXID FROM LOCKS WHERE BLOCKED = 1 ) , RES AS ( SELECT SYSDATE STATTIME, T1. NAME, T1. SESS_ID WT_SESSID, S. WT_TRXID, T2. SESS_ID BLK_SESSID, S. BLK_TRXID, T2. CLNT_IP, SF_GET_SESSION_SQL ( T1. SESS_ID) FULSQL, DATEDIFF ( SS, T1. LAST_SEND_TIME, SYSDATE) SS, T1. SQL_TEXT WT_SQL FROM LOCK_TR S, LOCKS T1, LOCKS T2 WHERE T1. LTYPE = 'OBJECT' AND T1. TABLE_ID <> 0 AND T2. LTYPE = 'OBJECT' AND T2. TABLE_ID <> 0 AND S. WT_TRXID = T1. TRX_ID AND S. BLK_TRXID = T2. TRX_ID) SELECT DISTINCT WT_SQL, CLNT_IP, SS, WT_TRXID, BLK_TRXID FROM RES;
查询死锁历史事务信息 (性能) select dh. trx_id , sh. sess_id, wm_concat( top_sql_text) from V$DEADLOCK_HISTORY dh, V$SQL_HISTORY sh where dh. trx_id = sh. trx_id and dh. sess_id= sh. sess_id group by dh. trx_id, sh. sess_id;
有事务未提交的表查询 SELECT b. object_name, c. sess_id, a. * FROM v$lock a, dba_objects b, v$sessions c WHERE a. table_id = b. object_id AND ltype = 'OBJECT' AND a. trx_id = c. trx_id;
内存监控 select ( select sum ( n_pages * page_size) / 1024 / 1024 from v$bufferpool ) || 'MB' as BUFFER_SIZE, ( select sum ( total_size) / 1024 / 1024 from v$mem_pool ) || 'MB' as mem_pool, ( select sum ( n_pages * page_size) / 1024 / 1024 from v$bufferpool ) + ( select sum ( total_size) / 1024 / 1024 from v$mem_pool ) || 'MB' as TOTAL_SIZE from dual; 以上查询结果中,字段含义如下: 1. BUFFER_SIZE:系统缓冲区大小,以 M 为单位。推荐值:系统缓冲区大小为可用物理内存的 60 % ~80 % 。有效值范围(8 ~ 1048576 ) 2. MEM_POOL:共享内存池大小,以 M 为单位。共享内存池是由 DM 管理的内存。有效值范围:32 位平台为(642000 ),64 位平台为(6467108864 ) 3. TOTAL_SIZE:BUFFER_SIZE 和 MEM_POOL 的总和。 内存不足常见原因有如下两种情况: 1. memory_target 设置为 0 ,导致会话使用的内存未释放,可以考虑修改 memory_target 参数。 2. 会话执行的 sql 消耗大量的内存,可以根据以下 sql 找到最占用内存的 sql ,再进行 sql 优化。 SELECT "SESSID" , MAX_MEM_USED|| 'KB' , SQL_TXT FROM V$SQL_STAT order by MAX_MEM_USED DESC ;
内存池使用情况 select name , stat_val/ 1024.0 / 1024.0 from v$sysstat where CLASSID = 11 ;
单个会话的内存使用情况 SELECT A. CREATOR , B. SQL_TEXT , SUM ( A. TOTAL_SIZE) / 1024.0 / 1024.0 TOTAL_M, SUM ( A. DATA_SIZE) / 1024.0 / 1024.0 DATA_SIZE_M FROM V$MEM_POOL A, V$SESSIONS B WHERE A. CREATOR = B. THRD_ID GROUP BY A. CREATOR, B. SQL_TEXT ORDER BY TOTAL_M DESC ;
内存增长过快分析(性能,内存) select ( select sum ( n_pages * page_size) / 1024 / 1024 from v$bufferpool) || 'MB' as BUFFER_SIZE, ( select sum ( total_size) / 1024 / 1024 from v$mem_pool) || 'MB' as mem_pool, ( select sum ( n_pages * page_size) / 1024 / 1024 from v$bufferpool) + ( select sum ( total_size) / 1024 / 1024 from v$mem_pool) || 'MB' as TOTAL_SIZEfrom dual; 在启动前查询上述语句,记录初始值。然后在内存增长的时候,再查询上述语句。 (2 )打开 MEMORY_LEAK_CHECK alter system set 'MEMORY_LEAK_CHECK' = 1 ; (3 )查询 V$MEM_REGINFO 视图,关注 REFNUM 字段,若该字段值很大,则说明存在内存堆积的情况。 select * from V$MEM_REGINFO ORDER BY REFNUM DESC ;
表空间使用情况(元数据信息) SELECT Upper( F. TABLESPACE_NAME) "表空间名" , D. TOT_GROOTTE_MB "表空间大小(M)" , D. TOT_GROOTTE_MB - F. TOTAL_BYTES "已使用空间(M)" , To_char( Round ( ( D. TOT_GROOTTE_MB - F. TOTAL_BYTES ) / D. TOT_GROOTTE_MB * 100 , 2 ) , '990.99' ) || '%' "使用比" , F. TOTAL_BYTES "空闲空间(M)" , F. MAX_BYTES "最大块(M)" FROM ( SELECT TABLESPACE_NAME, Round ( Sum ( BYTES) / ( 1024 * 1024 ) , 2 ) TOTAL_BYTES, Round ( Max ( BYTES) / ( 1024 * 1024 ) , 2 ) MAX_BYTES FROM SYS. DBA_FREE_SPACE GROUP BY TABLESPACE_NAME) F, ( SELECT DD. TABLESPACE_NAME, Round ( Sum ( DD. BYTES) / ( 1024 * 1024 ) , 2 ) TOT_GROOTTE_MB FROM SYS. DBA_DATA_FILES DD GROUP BY DD. TABLESPACE_NAME) D WHERE D. TABLESPACE_NAME = F. TABLESPACE_NAMEORDER BY 2 desc ;
查看表空间与数据文件的关系 SELECT TS. NAME, DF. PATH FROM V$TABLESPACE AS TS, V$DATAFILE AS DF WHERE TS. ID = DF. GROUP_ID;
查询表索引是否可用 select I. TABLE_OWNER, I. TABLE_NAME, O. OBJECT_NAME, O. OBJECT_TYPE, O. STATUS FROM USER_INDEXES I, USER_OBJECTS O WHERE O. OBJECT_NAME= I. INDEX_NAME AND O. STATUS = 'INVALID' ;
查询等待事件的具体信息 select THREAD_ID, TRX_ID, WAIT_CLASS, WAIT_OBJECT, WAIT_START, WAIT_TIME, SPACE_ID, FILE_ID, PAGE_NO FROM V$WAIT_HISTORY;
层次查询,根据指定的上下级关系字段 SELECT employee_id, employee_name, job_title, manager_id, department_id, LEVEL FROM dmhr. emp START WITH employee_id = 100 CONNECT BY PRIOR employee_id = manager_id ORDER SIBLINGS BY employee_id; 100 Steven, King President NULL 90 1 101 Neena, Kochhar Administration Vice President 100 90 2 108 Nancy, Greenberg Finance Manager 101 100 3 109 Daniel, Faviet Accountant 108 100 4 110 John, Chen Accountant 108 100 4 111 Ismael, Sciarra Accountant 108 100 4 112 Jose Manuel, Urman Accountant 108 100 4 113 Luis, Popp Accountant 108 100 4
在应用中发现执行较慢的 SQL,在管理工具中执行很快 可通过查看系统视图,及时发现活动会话中的慢 SQL ,将其在计划缓存中的执行计划打印到 trc 文件中,核查是否与在管理工具中查询到的执行计划一致,偏差较大则清理缓存中执行计划。 具体方法如下: 通过 PLNDUMP 来看对应缓存中的 SQL 执行计划 查找出活动会话中执行时间大于 1 S 的 SQL select * from ( select timestampdiff( second , s. last_recv_time, sysdate) t , s. * from v$sessions s where state= 'ACTIVE' ) where t > 1 找到对应慢 SQL 对应的 cache_item 值。 select * from v$cachepln where upper( sqlstr) like '%SQL%' 在 trace 目录中生成对应 trc 文件 alter session set events 'immediate trace name plndump ,level cache_item' 对比管理工具的执行计划和 . trc 文件中的执行计划。 清理内存中执行计划缓存。 call sp_clear_plan_cache( ) ; call sp_clear_plan_cache( pln号) ;
看某条 sql 语句每个操作符的执行时间 SF_SET_SESSION_PARA_VALUE( 'MONITOR_SQL_EXEC' , 1 ) ; select * from tablename[ 执行语句1 ] :select * from tablename执行成功, 执行耗时84 毫秒. 执行号:97812 DLCK 1 0.74 % 5 0 2 0 0 PRJT2 3 2.22 % 4 2 4 0 0 TOPN2 11 8.15 % 3 3 4 0 0 NSET2 50 37.04 % 2 1 3 0 0 CSCN2 70 51.85 % 1 4 2 0 0 如上图所示,该 sql 语句共涉及 5 个操作符,按照执行的先后顺序分别是 CSCN2、NSET2、TOPN2、PRJT2、DLCK。 其中,耗时最长的操作符是 CSCN2,耗时 70 微秒,占总执行时间的 51.85 % ;耗时排第二位的操作符是 NSET2,耗时 50 微秒,占总执行时间的 37.04 % 。 根据上述的分析,我们就需要针对这 2 个操作符进行针对性的优化。
大量的 DML 动作 (经常做增删改查) 导致表的碎片很多,最终导致查询该表性能很慢,如何解决(性能) 达梦的数据通过 B 树维护的。可对指定索引进行空间整理,重组数据,达到优化该表的目的。具体操作如下,以 test 为例介绍: select name from sysobjects where pid= ( select id from sysobjects where name= 'TEST' and type $= 'SCHOBJ' ) and subtype$= 'INDEX' ; INDEX33568488 INDEX33568489 INDEX108643191852292 SP_REORGANIZE_INDEX( 'SYSDBA' , 'INDEX33568488' ) ;
如何开启结果集缓存 修改 dm. ini 参数; vim / dmdata/ DAMENG/ dm. ini RS_CAN_CACHE= 1 BUILD_FORWARD_RS= 1 RS_CACHE_TABLES= HGTEST. YBCK_CBEC_ELIST_ITEM, HGTEST. YBCK_CBEC_ELIST 当 RS_CAN_CACHE 为 1 时,还可以通过设置 INI 参数 RS_CACHE_TABLES 和 RS_CACHE_MIN_TIME 对缓存的结果集进行限制和过滤。RS_CACHE_TABLES 指定可以缓存结果集的基表清单,只有查询涉及的所有基表全部在参数指定范围内,此查询才会缓存结果集。RS_CACHE_MIN_TIME 则指定了缓存结果集的查询语句执行时间的下限,只有实际执行时间不少于指定值的查询结果集才会缓存。 参数详情可以查看下方表格’参数说明‘ 验证 dm. ini 修改是否正确; select * from v$dm_ini where PARA_NAME in ( 'RS_CAN_CACHE' , 'BUILD_FORWARD_RS' , 'RS_CACHE_TABLES' ) ; 重启数据库生效。 验证结果集缓存发现第一次查询慢 第二次查询就会快
参数说明:
参数名 默认值 说明 属性 RS_CAN_CACHE 0 结果集缓存配置。 0:禁止重用结果集; 1:强制模式,此时默认缓存所有结果集, 但可通过 RS_CACHE_TABLES 参数和语句 HINT 进行手动设置; 2:手动模式,此时默认不缓存结果集, 但可通过语句 HINT 对必要的结果集进行 缓存 静态 BUILD_FORWARD_RS 0 仅向前游标是否生成结果集。 0:不生成; 1:生成 静态 RS_CACHE_TABLES 空串 指定可以缓存结果集的基表的清单, 当 RS_CAN_CACHE=1 时,只有查 询涉及的所有基表全部在此参数指 定范围内,该查询才会缓存结果集。 当参数值为空串时,此参数失效。 手动 RS_CACHE_MIN_TIME 结果集缓存的语句执行时间下限,只 有实际执行时间不少于指定时间值的 查询,其结果集才会被缓存,仅在 RS_CAN_CACHE=1 时有效。默认值 0, 表示不限制;有效值范围(0~4294967294) ,以 MS 为单位。 动态,系统级
如何使用 DBMS_SQLTUNE 包获取 SQL 执行信息 DBMS_SQLTUNE 包提供一系列对实时 SQL 监控的方法。当 SQL 监控功能开启后,DBMS_SQLTUNE 包可以实时监控 SQL 执行过程中的信息,包括:执行时间、执行代价、执行用户、统计信息等情况。SQL 监控功能开启的方法是将 DM. INI 参数 ENABLE_MONITOR 和 MONITOR_SQL_EXEC 均设置为 1 。 示例: sp_set_para_value( 1 , 'ENABLE_MONITOR' , 1 ) ; sf_set_session_para_value( 'MONITOR_SQL_EXEC' , 1 ) ; 需要优化的sql select * from tablename; 通过消息可以查询到执行号,我这里是97828 调用DBMS_SQLTUNE函数传入执行号: select DBMS_SQLTUNE. REPORT_SQL_MONITOR( SQL_EXEC_ID= > 97828 ) from dual; 下面是执行打印的结果: SQL Monitoring ReportSQL Text select * from zcjy_tdnz. ht_landGlobal Information Status : DONE ( ALL ROWS ) Session : SYSDBA ( 140599657854928 :1260 ) SQL ID : 13090 SQL Execution ID : 97828 Execution Started : 2024 - 04 - 01 20 :43 :09 Duration : 0.155809 s Program : manager. exe Global Stats= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = | Affected | Bytes | Bytes | Physical | Logical | | Rows | Allocate | Free | Read ( page) | Read ( page) | = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = | 100 | 0 | 0 | 100 | 20 | = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = SQL Plan 1 2 3
语句备份表 create table table1 as select * from table2 where 1 = 2 ; create table table1 as select * from table2 ; create table table1( 新列名1 , 新列名2 ) as select 原列名1 , 原列名2 from table2;
修改表信息 ALTER TABLE 表名 ADD COLUMN 字段名称 字段类型
确定高负载的 SQL select * from V$SYSTEM_LONG_EXEC_SQLSselect * from V$LONG_EXEC_SQLSsf_get_session_sql( sess_id)
查询函数和存储过程中的执行计划 select cache_item, sqlstr from v$cachepln where sqlstr like '%functionname%' ; ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME PLNDUMP,LEVEL 140015356688432' ; sub_method[ 1 ] :: PLN[ 140163083606064 ] [ PTEST1] ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME PLNDUMP,LEVEL 140163083606064' ;
当 in 查询一个集合 闯入的是字符串的时候 select * from a where name in ( 'a,b,c,d' ) ( select regexp_substr( 'jcd12,jcd13,jcd14' , '[^,]+' , 1 , level , 'i' ) as tempcol from dual connect by level <= LENGTH( TRANSLATE( 'jcd12,jcd13,jcd14' , ',' || 'jcd12,jcd13,jcd14' , ',' ) ) + 1 ) select * from a where name in ( select regexp_substr( 'a,b,c,d' , '[^,]+' , 1 , level , 'i' ) as tempcol from dual connect by level <= LENGTH( TRANSLATE( 'a,b,c,d' , ',' || 'a,b,c,d' , ',' ) ) + 1 )
排查页面执行慢 管理工具执行快的问题 通过 PLNDUMP 来看对应缓存中的 SQL 执行计划
查询到模式名称、表个数、有注释信息的表个数、有注释信息的表比例、无查询权限的表名 select distinct 'select a.table_name,a.n,b.n,round((b.n*1.0/a.n)*100,2)||''%'' from (select count(*) as n,''' || OBJECT_NAME|| ''' as table_name from dba_tables where owner = ''' || OBJECT_NAME|| ''') a,(select count(*) as n,''' || OBJECT_NAME|| ''' as table_name from SYSTABLECOMMENTS where schname = ''' || OBJECT_NAME|| ''') b where a.table_name = b.table_name union all' from ALL_OBJECTS where OBJECT_TYPE = 'SCH' 模式名称 表个数 有注释信息的表个数 有注释信息的表比例 table_name n n round ( ( b. n* 1. / a. n) * 100 , 2 ) || '%' ZCJY_ZS 619 4 0.65 %
查询当前模式下的所有表名 select table_name from dba_tables where owner = '模式名' order by table_name table_name table_a table_b select count ( * ) from dba_tables where owner = '模式名' COUNT ( * ) 859
查询当前模式下所有带有注释信息的表名 select tvname, comment $ from SYSTABLECOMMENTS where schname = '模式名' order by tvnametvname comment $ SJYH 手机用户 SJDX 手机短信
查询模式名称、表名称、表名称注释、字段名称、字段名称注释、字符类型、字符长度、是否可为空 (表信息) 模式名称 表名称 是否有表名称注释 表名称注释 总字段个数 有注释信息的字段个数 有注释信息的字段比例 是否为空表 数据量 select owner, table_name, 'select a.owner,a.tvname,a.n,b.n,round((b.n*1.0/a.n)*100,2)||''%'' from (select count(*) as n,''' || owner|| ''' as owner,''' || table_name|| ''' as tvname from all_tab_columns where owner = ''' || owner|| ''' and table_name = ''' || table_name|| ''') a,(select count(*) as n,''' || owner|| ''' as owner,''' || table_name|| ''' as tvname from SYSCOLUMNCOMMENTS where schname = ''' || owner|| ''' and tvname = ''' || table_name|| ''') b where a.owner = b.owner and a.tvname = b.tvname union all' from dba_tables where owner = 'DB_TEST' order by owner, table_nameselect 'select ''' || owner|| ''' as owner,''' || table_name|| ''' as tvname,count(*) from "' || owner|| '"."' || table_name|| '" union all ' from dba_tables where owner = 'DB_TEST' order by owner, table_nameselect a. table_name, b. comment $ from ( select table_name from dba_tables where owner = 'ODS_TEST' order by table_name) aleft join ( select tvname, comment $ from SYSTABLECOMMENTS where schname = 'DB_TEST' ) bon a. table_name = b. tvname
查询模式名称、表名称、表名称注释、字段名称、字段名称注释、字符类型、字符长度、是否可为空 select owner, table_name, column_name, data_type, data_length, nullable from all_tab_columns where owner like 'DB_TEST%' owner table_name column_name data_type data_length nullable DB_TEST ODS_TEST ACCOUNT_ID VARCHAR 32 N
查看 sql 语句执行的执行情况 select * from V$SQL_STAT where sessid = '139454492043355' ; MAX_MEM_USED - 内存使用情况 (kb) IO_WAIT_TIME - io 等待时间 (毫秒) 可能可服务器的磁盘性能有问题 EXEC_TIME - 总执行时间(毫秒)
创建函数,函数功能是返回一个表的结果集 create or replace type report_01 as object( m1 varchar ( 50 ) , s1 decimal ( 18 , 0 ) ) ; create or replace type report_01_table as table of report_01; CREATE OR REPLACE FUNCTION "fn_report" ( "v_type" varchar ( 50 ) ) RETURN report_01_tableAUTHID DEFINER is v_text report_01_table := report_01_table( ) ; begin select report_01( m1, s1 ) bulk collect into v_text from ( select '合计' as m1, 1000 as s1) dd; return v_text; end fn_report; select * from table ( fn_report( 'test' ) ) ;
# 优化经验如果服务器的 cpu 核心数足够大,可以设置并行度查询
select para_name, para_value from v$dm_ini where para_name= 'PARALLEL_POLICY' select * from table
需要排查是否是 io 等待的时间比较久
可以通过以下sql 查询io情况: select * from V$SQL_STAT where sessid = '139454492043355' ; 看 IO_WAIT_TIME 的耗时