资讯动态

达梦数据库性能优化常用手段

发布时间:2026/9/2 7:36:04 来源:尧图企业网站定制
在数据库运维与开发工作中SQL 性能问题往往是最具挑战性的问题之一本文系统梳理了达梦性能优化的核心手段涵盖抓取问题 SQL、分析锁与阻塞分析、 执行计划查看与诊断、HINT 人工干预执行计划以及执行计划绑定等常用实战场景。一、数据库系统视图在达梦数据库性能优化中系统动态性能视图是 DBA 进行深度诊断与性能剖析的核心工具。依托达梦数据库丰富的内部监控视图运维人员能够实现数据库性能的精准调优与故障溯源。1.1常用视图V\$SESSIONS: 显示当前数据库中所有会话的信息如执行的 sql 语句、主机名、当前会话状态、用户名等等。配合V$LOCK使用。V\$TRX显示所有活动事务的信息。通过该视图可以查看所有系统中所有的事务以及相关信息如锁信息等。V\$SQL_STAT: 记录当前正在执行的 SQL 语句的资源开销。V\$SQLTEXT记录SQL 缓冲区中的 SQL 语句的相关信息。V\$TRXWAIT显示当前事务等待信息助于排查锁阻塞问题。V\$SQL_HISTORY: 显示执行 SQL 的历史记录信息可以方便用户经常使用的记录进行保存。V\$SESSION_HISTORY: 显示当前会话历史的记录信息如主机名、用户名等与 V$SESSIONS 的区别在于会话历史记录只记录了会话一部分信息对于一些动态改变的信息没有记录如执行的 SQL 语句等。V\$DMSQL_EXEC_TIME: 记录动态监控的 SQL 语句执行时间仅监控多条或复杂 SQL例如包含引用包、嵌套子过程、子方法、动态 SQL 的 SQL 语句。V\$LONG_EXEC_SQLS或 V$SYSTEM_LONG_EXEC_SQLS: 前者显示最近 1000 条执行时间较长的 SQL 语句后者显示服务器启动以来执行时间最长的 300条 SQL 语句。V\$PLN_HISTORY显示近期执行的 SQL 语句的执行计划。V\$BUFFERPOOL页面缓冲区动态性能表用来记录页面缓冲区结构的信息。V\$MEM_POOL内存池相关信息记录视图。V\$CACHEPLN显示 SQL 缓冲区中的计划缓存的相关信息。1.2定位性能问题常用SQL语句1.2.1 抓取问题SQL已执行超过2秒的活动SQLselect * from (SELECT sess_id,sql_text,datediff(ss,last_send_time,sysdate) Y_EXETIME,SF_GET_SESSION_SQL(SESS_ID) fullsql,clnt_ipFROM V\$SESSIONS WHERE STATEACTIVE)where Y_EXETIME2;查活跃会话和最近执行的SQLSELECTT.ID AS TRX_ID,S.SESS_ID,S.USER_NAME,S.CLNT_IP AS 客户端IP,S.APPNAME AS 应用名称,S.STATE AS 会话状态, -- ACTIVE正在执行 / IDLE空闲未提交T.START_TIME AS 事务启动时间,ROUND((SYSDATE - T.START_TIME)*86400,2) AS 事务持续秒数,T.INS_CNT,T.UPD_CNT,T.DEL_CNT,SF_GET_SESSION_SQL(S.SESS_ID) AS 当前完整SQLFROM V\$TRX T LEFT JOIN V\$SESSIONS S ON T.SESS_ID S.SESS_IDWHERE T.STATUSACTIVEORDER BY T.START_TIME ASC;对于历史发生的性能问题 可以通过视图 V\$ACTIVE_SESSION_HISTORY 进行追溯 以下 SQL 展示指定时间范围内 CPU 使用率最高的 SQL_IDSELECT TOP 10 SQL_ID, COUNT(*) CNT, ROUND(COUNT(*)/SUM(COUNT(*)) OVER(), 2) PCTLOADFROM V\$ACTIVE_SESSION_HISTORYWHERE SAMPLE_TIME BETWEEN ? AND ? AND SESSION_TYPE BACKGROUND AND SESSION_STATE ON CPUGROUP BY SQL_IDORDER BY 2 DESC;找慢SQL可以根据需求按耗时、逻辑读次数、物理读次数排序SELECTSESS_ID AS 会话ID,TOP_SQL_TEXT AS SQL预览,START_TIME AS 开始时间,TIME_USED AS 耗时(微秒),N_LOGIC_READ AS 逻辑读,N_PHY_READ AS 物理读,CASE HARD_PARSE_FLAGWHEN 0 THEN 软解析WHEN 1 THEN 语义解析WHEN 2 THEN 硬解析END AS 解析方式FROM V\$SQL_HISTORYORDER BY TIME_USED DESCFETCH FIRST 20 ROWS ONLY;物理读次数TOP20SQLSELECTSQL_ID, SUBSTR(TOP_SQL_TEXT, 1, 100) AS SQL_PREVIEW, N_PHY_READ, -- 物理读次数N_LOGIC_READ, -- 逻辑读次数TIME_USED FROM V\$SQL_HISTORY -- 过滤条件可以根据实际情况放宽或收紧ORDER BY N_PHY_READ DESCFETCH FIRST 20 ROWS ONLY;逻辑读次数TOP20SQLSELECTSQL_ID, SUBSTR(TOP_SQL_TEXT, 1, 100) AS SQL_PREVIEW, N_PHY_READ, -- 物理读次数N_LOGIC_READ, -- 逻辑读次数TIME_USED FROM V\$SQL_HISTORY -- 过滤条件可以根据实际情况放宽或收紧ORDER BY N_LOGIC_READ DESCFETCH FIRST 20 ROWS ONLY;定位占用内存大的 sqlwith cte as( select regexp_replace(name, [0-9]),count(*),trunc(sum((org_size / 1024.0 / 1024))) 初始,trunc(sum((data_size / 1024.0 / 1024))) 在用,trunc(sum((total_size / 1024.0 / 1024))) 总的,trunc(sum((target_size / 1024.0 / 1024))) 水位,max(creator) as thrd_id from v\$mem_pool group by regexp_replace(name, [0-9]))select *, (select sql_text from v\$sessions where thrd_id a.thrd_id) as sql_textfrom cte a order by 总的 desc;如果当前会话中找不到高内存的 sql 可通过 v\$sql_stat_history 视图 协助定位找到使用较高内存的 sqlselect max_mem_used/1024.0/1024.0 as GB,* from v\$sql_stat_history order by 1 desc;1.2.2 查询锁与阻塞查所有锁信息SELECT TRX_ID,ADDR,LTYPE,LMODE,BLOCKED FROM V\$LOCK;查表锁SELECT t2.name,t1.TABLE_ID,t1.LTYPE,t1.BLOCKED,t1.LMODE,t1.TRX_ID,t1.addr,t1.ROW_IDX,t2.SCHID FROM V\$LOCK t1,sysobjects t2 where t1.table_idt2.id;锁等待查询select o.name,l.* from v\$lock l,sysobjects o where l.table_ido.id and blocked1;阻塞查询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 swhere l.table_ido.id and l.trx_ids.trx_id ),lock_tr as ( select trx_id wt_trxid,row_idx blk_trxid from locks where blocked1),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 t2where t1.ltypeOBJECT and t1.table_id0 and t2.ltypeOBJECT and t2.table_id0and s.wt_trxidt1.trx_id and s.blk_trxidt2.trx_id)select distinct wt_sql,clnt_ip,ss,wt_trxid,blk_trxid from res;查询被阻塞的信息和引起阻塞的信息SELECT SYSDATE STATTIME, DATEDIFF(SS, S1.LAST_SEND_TIME, SYSDATE)ss,被阻塞的信息 WT,S1.SESS_ID WT_SESS_ID,S1.SQL_TEXT WT_SQL_TEXT,S1.STATE WT_STATE,S1.TRX_ID WT_TRX_ID,S1.USER_NAME WT_USER_NAME,S1.CLNT_IP WT_CLNT_IP,S1.APPNAME WT_APPNAME,S1.LAST_SEND_TIME WT_LAST_SEND_TIME,引起阻塞的信息 FM,S2.SESS_ID FM_SESS_ID,S2.SQL_TEXT FM_SQL_TEXT,S2.STATE FM_STATE,S2.TRX_ID FX_TRX_ID,S2.USER_NAME FM_USER_NAME, S2.CLNT_IP FM_CLNT_IP,S2.APPNAME FM_APPNAME, S2. LAST_SEND_TIME FM_LAST_SEND_TIMEFROM V\$SESSIONS S1,V\$SESSIONS S2,V\$TRXWAIT WWHERE S1.TRX_IDW.IDAND S2.TRX_IDW.WAIT_FOR_ID;1.2.3 执行计划相关查询近期执行的 SQL 语句的执行计划select * from V\$PLN_HISTORY where TOP_SQL_TEXT like %select * from test2.SALES_DATA WHERE sale_id 8888%;二、系统包2.1DBMS_SQLTUNE 包DBMS_SQLTUNE 包提供一系列对实时 SQL 监控的方法。当 SQL 监控功能开启后 DBMS_SQLTUNE 包可以实时监控 SQL 执行过程中的信息包括执行时间、执行代价、执行用户、统计信息等情况。同时还可以创建调优任务给出优化建议。SQL 监 控 功 能 开 启 的 方 法 是 将 DM.INI 参 数 ENABLE_MONITOR 和MONITOR_SQL_EXEC 均设置为 1。使用包内的过程和函数之前如果还未创建过系统包请先调用系统过程创建系统包。SP_CREATE_SYSTEM_PACKAGES (1,DBMS_SQLTUNE);开启 SQL 监控开关。设置 DM.INI 参数 ENABLE_MONITOR 和 MONITOR_SQL_EXEC 为 1。SP_SET_PARA_VALUE (1,ENABLE_MONITOR,1);SP_SET_PARA_VALUE (1,MONITOR_SQL_EXEC,1);为了防止开启MONITOR_SQL_EXEC导致数据库性能问题可以在会话级开启call SF_SET_SESSION_PARA_VALUE(MONITOR_SQL_EXEC,1);2.1.1 监控SQL语句1.执行要优化的sqlSQL select * from test2.SALES_DATA WHERE sale_id 100000;行号 SALE_ID SALE_DATE REGION AMOUNT---------- ----------- ---------- --------------- ------1 100000 2024-03-13 LDgb9VjGUCCKgKH 6226已用时间: 19.283(毫秒). 执行号:4015.执行号就是SQL_EXEC_ID2.查看sql监控报告SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR(SQL_EXEC_ID4015) FROM DUAL;3.查询 SQL 监控报告链表SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR_LIST() FROM DUAL;2.1.2 SQL语句优化1. 创建语句调优任务。DBMS_SQLTUNE.CREATE_TUNING_TASK(select * from test2.SALES_DATA WHERE sale_id 100000, TASK_NAMETASK1);2. 执行语句调优任务。DBMS_SQLTUNE.EXECUTE_TUNING_TASK(TASK1);3. 输出语句调优报告。//首先将环境变量 LONG 设置成一个较大值 999999以保证完整显示调优报告SET LONG 999999SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK(TASK1);4.删除语句调优任务DBMS_SQLTUNE.DROP_TUNING_TASK(TASK1);2.2DBMS_XPLAN 包为了更好展示历史执行计划达梦提供了 DBMS_XPLAN 系统包。 DBMS_XPLAN 包用于展示历史执行计划以及对持久化的历史执行计划进行清除。仅 当 历 史 执 行 计 划 持 久 化 功 能 打 开 USE_PLN_POOL!0 ENABLE_MONITOR_PLNHIST1时使用 DBMS_XPLAN 包才有意义。 不支持 DMDPC 环境下记录历史执行计划。修改ENABLE_MONITOR_PLNHIST参数SP_SET_PARA_VALUE (1,ENABLE_MONITOR_PLNHIST,1);1.执行查询SQLselect * from test2.SALES_DATA WHERE sale_id 100000;2.将历史执行计划信息刷盘到系统表SYSPLANHIST 中SP_FLUSH_HIST_PLAN;3.使用DISPLAY_PLANHIST方法查看历史计划DBMS_XPLAN.DISPLAY_PLANHIST(select * from test2.SALES_DATA WHERE sale_id 100000;) ;4.可以到v\$sqltexthash_value或sysplanhist(plan_hash_value)中获取sql哈希值select SQL_TEXT,HASH_VALUE from v\$sqltext where SQL_TEXT like %test2.SALES_DATA%;DBMS_XPLAN.DISPLAY_PLANHIST(1758351538);6.使用CLEAR_PLANHIST清理指定时间范围的历史执行计划DBMS_XPLAN.CLEAR_PLANHIST(2026-07-11 12:00:00,2026-07-18 19:00:00);三、trace3.1 trace 10053在sql执行过程中可能存在sql执行时间同实际执行时间和预期严重不符的情况这种情况下需要打印sql的实际执行计划根据实际计划来判断执行计划缓慢节点。数据库提供各种trace文件来进行辅助分析sql的执行计划选择这里介绍10053事件该Trace文件中一般给出几种计划路径可能通过对比相关计划的代价选出最优的计划进行执行。10053 Trace 文件的内容是以查询语句为单位的 Trace10053 的文件结构如下表10053 trace追踪过程1.设置会话trace事件alter session set events 10053 trace name context forever;在session设置10053诊断事件后会在数据库trace目录下生成sql解析的相关日志一般为数据库数据文件存放目录trace目录下2.执行SQLselect * from test2.SALES_DATA WHERE sale_id 8888;3.查看trace文件4.关闭会话tracealter session set events 10053 trace name context off;3.2 disql autotrace传参语句与直接赋值语句可能会表现出执行计划不一致而应用执行的实际上是传参的执行计划 在数据分布不均时 优化器估算偏差不可避免 可利用disql 的 set autotrace trace 命令来显示 sql 执行的真实计划 每个操作符中包含预估行数实际行数其不仅可快速协助判断统计信息是否失真还可利用其实际行数来使用一些hint 调试计划。disql常用参数使用autotrace后打印执行会对统计信息不正确处进行提示显示实际的统计信息同时对hash连接、hash分组、去重等操作是否数据刷盘到临时表空间DISK_USED,同时会有总体统计打印一些资源消耗统计信息。若存在数据刷盘情况可以考虑放大HJ_BUF_SIZE、JOIN_HASH_SIZE 或使用动态HASHUSE_DHASH_FLAG3打开AUTOTRACE步骤1.使用disql登录2.SF_SET_SESSION_PARA_VALUE(MONITOR_SQL_EXEC,1);3.SET AUTOTRACE TRACE3.3 traceplndump由于变量窥探和绑定参数的问题 在客户端执行 explain 出来的计划不是实际应用真正执行 的计划 这里有两种方式来查看真正的执行计划 第一个是用 disql 的 autotrace。 另一个方法是使用 plndump 事件1.获取 sql 在计划池中的 cacheitemselect CACHE_ITEM from v\$cachepln where sqlstr like %select * from test2.SALES_DATA WHERE sale_id 8888%;2.dump 出该 cacheitem 的内容alter SESSION SET EVENTS immediate trace name plndump level 140037461135848, DUMP_FILE test1.trc;--注该 sql 中出现的引号均为单引号3.新版本8.1.4.112开始支持 通过sql直接查看select SF_TRACE_DUMP_PLN(140037461135848);四、ET工具ET 工具是 DM 数据库自带的 SQL 性能分析工具能够统计 SQL 语句执行过程中每个操作符的实际开销为 SQL 优化提供依据以及指导。1. 功能的开启/关闭ET 功能默认关闭可通过配置 INI 参数中的 ENABLE_MONITOR1、MONITOR_SQL_EXEC1 开启该功能。由于ET 功能的开启将对数据库整体性能造成一定影响建议会话级开启避免对实时系统造成影响。SF_SET_SESSION_PARA_VALUE(MONITOR_SQL_EXEC,1);2. 查看方式执行 SQL 语句后客户端会返回 SQL 语句的执行号。单击执行号即可查看 SQL 语句对应的 ET 结果。如果没有图形界面调用存储过程可返回相同结果。CALL ET(725);ET 结果说明OP: 操作符TIME(us): 时间开销单位为微秒PERCENT: 执行时间占总时间百分比RANK: 执行时间耗时排序SEQ: 执行计划节点号N_ENTER: 进入次数五、HINTDM 查询优化器采用基于代价的方法。在估计代价时主要以统计信息或者数据分布为依据。通常情况下估计的代价都是准确的。但在一些估算代价的依据极度缺乏的情况下例如缺少统计信息、或统计信息陈旧、或抽样数据不能很好地反映数据分布时优化器选择的执行计划可能不是最优的。然而 DBA 对于数据分布是很清楚的并且知道 SQL 语句按照哪种方法执行会最快。在面临上述优化器选择的执行计划不是最优的情况下DBA 可以主动进行人工干预指示优化器按照指定的方法去选择 SQL 的执行计划。这种人工干预优化器的方法称为 HINT。优化器可根据 DBA 的 HINT 提示来生成指定的执行计划。如果优化器无法根据给定的 HINT 生成相应的执行计划那么将忽略该 HINT。HINT 的常见用法如下所示1.访问路径类-- 强制走指定索引SELECT /* INDEX(e, IDX_EMP_DEPT) */ * FROM emp e WHERE dept_id 10;-- 强制全表扫描常用于验证索引失效后回退到 FULL 是否更快或表极小场景SELECT /* FULL(e) */ * FROM emp e;-- 禁止使用某索引SELECT /* NO_INDEX(e, IDX_EMP_DEPT) */ * FROM emp e WHERE dept_id 10;2.连接方法与连接顺序类-- 强制哈希连接两大表等值连接常见优选SELECT /* USE_HASH(a, b) */ * FROM ta a, tb b WHERE a.id b.id;-- 强制嵌套循环小表驱动 被驱动表有高效索引SELECT /* USE_NL(a, b) */ * FROM ta a, tb b WHERE a.id b.id;-- 强制归并连接两表连接列均已排序/有有序索引SELECT /* USE_MERGE(a, b) */ * FROM ta a, tb b WHERE a.id b.id;-- 指定驱动表 / 连接顺序SELECT /* LEADING(a) / * FROM ta a, tb b, tc c WHERE ...;SELECT / ORDERED */ * FROM ta a, tb b WHERE ...; -- 按 FROM 书写顺序展开3.并行与资源类-- 语句级开并行SELECT /* PARALLEL(4) / COUNT() FROM huge_tab;-- 关并行SELECT /* NO_PARALLEL */ * FROM huge_tab;需要注意的是如果 HINT 的语法没有写对或指定的值不正确DM 并不会报错而是直接忽略 HINT 继续执行。4.语句级 INI 参数 HINT-- 本语句内把哈希连接开关打开SELECT /* ENABLE_HASH_JOIN(1) */ * FROM T1, T2 WHERE C1 D1;哪些 INI 参数允许设置可以通过下面sql查询SELECT * FROM V\$HINT_INI_INFO;其中 HINT_TYPEOPT是分析阶段生效EXEC是运行阶段生效后者对视图可能无效。六、绑定执行计划1.设置参数 LOAD_BINDED_PLN1sp_set_para_value(1,LOAD_BINDED_PLN,1);2.通过查询执行计划缓存视图找到 SQL 需要绑定的正确执行计划缓存的 hash 值。select * from v\$cachepln where sqlstr like %select * from test2.SALES_DATA WHERE sale_id 8888%;3.绑定执行计划通过语句 hash 值绑定执行计划。SP_SET_PLN_BINDED(1232045173, SYSDBA, SQL, 1); ---1为内存中绑定0解除内存绑定SP_SET_PLN_BINDED(1232045173, SYSDBA, SQL, 2);----2为持久化绑定4.如果想取消绑定清理计划缓存即可。--查询系统中绑定执行计划持久化的信息。select * from SYSPLNINFO;--查询系统中绑定执行计划对应字典对象的信息。select * from SYSPLNOBJID;--清理计划缓存1为SYSPLNINFO中查出的PLN_IDSP_REMOVE_STORE_PLN(1);参数说明1LOAD_BINDED_PLN 动态系统级默认值 0 是否从系统表 SYSPLNINFO 加载已持久化的绑定计划。1:加载;0:不加载。2SP_SET_PLN_BINDED(sql_text/hash_value,schname,type,binded)sql_text执行计划对应的 SQL 语句该语句可以从动态视图 V\$SQL_PLAN 中的 SQLSTR 列获得。hash_value执行计划的哈希值其值可以从动态视图 V\$SQL_PLAN 中的 HASH_VALUE 列获得。schname执行计划的模式名。type执行计划的类型可取值SQL查询语句类型PL/OBJ存储过程或触发器类型。binded是否绑定执行计划可取值0、1、2。0解除内存中绑定1内存中绑定2持久化绑定。解除持久化绑定可以通过系统过程函数 SP_REMOVE_STORE_PLN 完成。对于长度超过 1000 字节的 SQL 语句建议使用内存中绑定。由于持久化绑定只保存 SQL 语句的前 1000 字节通过执行计划哈希值以及前 1000 字节字符共同校验以查找计划故可能存在 SQL 语句不同但哈希值相同的情况导致查找到错误的计划。ps:达梦数据库社区地址https://eco.dameng.com

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价