把一条慢SQL分析完整,需要看哪些信息
|
admin
2026年4月24日 15:37
本文热度 67
|
介绍
很多时候我们拿到一条执行慢、结果异常或者资源消耗偏高的SQL,第一反应都是先去看执行计划。但真正分析下来就会发现,执行计划只是其中一块信息。
还需要知道这条SQL实际访问了哪些表,表本身有多大,是不是分区表,表上有哪些索引,统计信息是不是过旧,执行过程中时间到底耗在了哪个节点上,必要的时候甚至还要把缓存中的执行计划导出来继续看。少看一块,判断就可能偏。
这些信息在达梦的系统视图和系统表里都能查到,但这些信息分散在不同的系统视图中。平时查一条SQL往往是先翻执行历史,再补对象信息,再查索引和统计信息,最后再回来看计划和节点耗时。当SQL语句涉及的表特别多时会特别麻烦。
DM_SQL_RPT包
基于上述原因,DM_SQL_RPT是一个达梦的PACKAGE包,通过每个功能封装存储过程的形式,把原本分散的分析动作做成了一套固定流程。
核心思路:通过SQL语句执行后返回的EXEC_ID,去收集对象、索引、统计信息、执行计划、运行时节点信息以及缓存计划。尽量把和这次执行有关的关键视角一次性收集输出。
具体模块说明
DM_SQL_RPT目前包含六个采集模块,分别负责表信息、索引信息、统计信息、执行计划、ET 节点运行信息以及缓存执行计划导出。
1. 表信息模块:先通过V$SQL_HISTORY和 V$SQL_PLAN结合EXEC_ID找到本次执行关联到的对象ID,再回到SYSOBJECTS里把对象解析成schema 和表名。定位表后获取对用的列定义、表的统计信息、区分表等相关数据。
2. 索引信息模块:先从V$SQL_HISTORY和V$SQL_PLAN找到当前 SQL 涉及的表,再通过SYSOBJECTS、SYSINDEXES、SYSCOLUMNS去展开这些表上的索引信息。
3. 统计信息模块:先通过V$SQL_HISTORY和 V$SQL_PLAN锁定目标表,再从SYSSTATS结合SYSOBJECTS、SYSCOLUMNS去取列级统计信息。如果表上没有可用统计信息,会提示为空。
4. 执行计划模块:先通过V$SQL_HISTORY和V$SQL_PLAN找到对应的 SQL_ID和计划地址,再从V$SQL_PLAN_NODE把节点级信息取出来,按层级重新组织成一棵便于阅读的计划树。
5. ET节点运行信息模块:直接读取V$SQL_NODE_HISTORY和V$SQL_NODE_NAME,把每个节点的耗时、耗时占比、进入次数、内存占用、磁盘占用以及哈希使用和冲突情况整理出来。
6. 缓存执行计划导出:通过V$CACHEPLN、V$SQL_PLAN和 V$SQL_HISTORY把本次执行关联到缓存计划项,再通过V$DM_INI读取 TRACE_PATH,把缓存中的执行计划导出到 trace 文件里。
使用示例
提供的这个示例即为完整过程
1. 将脚本的SQL语句放到数据库中执行
2. disql工具中开启MONITOR_SQL_EXEC参数
3. 开启set serveroutput on
4. 执行慢SQL
5. 执行脚本中包的功能函数
此时会输出SQL的关联表的信息以及表字段和表的索引信息。最下面就是SQL的执行计划以及ET信息。
SQL> SF_SET_SESSION_PARA_VALUE ('MONITOR_SQL_EXEC', 1);DMSQL executed successfullyused time: 0.752(ms). Execute id is 69801.
SQL> set serveroutput on
SQL> select a.id,a.c1,b.c1 from test_left01 a join test_left02 b on a.id=b.id;used time: 28.112(ms). Execute id is 69803.
SQL> call DM_SQL_RPT.GET_ALL_INFO(69803); ###################################################################################### TABLE INFO : SYSDBA.TEST_LEFT01| OWNER| TABLE_NAME| NUM_ROWS| LAST_ANALYZED| PARTITIONED| TEMPORARY|| SYSDBA| TEST_LEFT01| NULL| NULL| NO| N|##### COLUMN INFO : SYSDBA.TEST_LEFT01| COLUMN_ID| COLUMN_NAME| COLUMN_TYPE| NULLABLE| DEFAULT_VAL|| 1| ID| VARCHAR(100,0)| Y| NULL|| 2| C1| INT(4,0)| Y| NULL|| 3| C2| VARCHAR(100,0)| Y| NULL|###################################################################################### TABLE INFO : SYSDBA.TEST_LEFT02| OWNER| TABLE_NAME| NUM_ROWS| LAST_ANALYZED| PARTITIONED| TEMPORARY|| SYSDBA| TEST_LEFT02| NULL| NULL| NO| N|##### COLUMN INFO : SYSDBA.TEST_LEFT02| COLUMN_ID| COLUMN_NAME| COLUMN_TYPE| NULLABLE| DEFAULT_VAL|| 1| ID| VARCHAR(100,0)| N| NULL|| 2| C1| VARCHAR(100,0)| Y| NULL|| 3| C2| VARCHAR(100,0)| Y| NULL|| 4| C3| CLOB(2147483647,0)| Y| NULL|######################################################################################################### INDEX INFO : SYSDBA.TEST_LEFT01CREATE OR REPLACE INDEX "SYSDBA"."IX_TEST_LEFT01" ON "SYSDBA"."TEST_LEFT01"("ID" ASC,"C1" ASC) STORAGE(ON "MAIN", CLUSTERBTR) ;| ID| INDEX_NAME| COLUMN_NAME| COLUMN_POSITION| DESCEND| TYPE| XTYPE| FLAG|| 33555472| IX_TEST_LEFT01| ID| 1| ASC| BT| SEC| 0|| 33555472| IX_TEST_LEFT01| C1| 2| ASC| BT| SEC| 0|######################################################################################################### INDEX INFO : SYSDBA.TEST_LEFT02The index created by system is forbidden to indexdef.| ID| INDEX_NAME| COLUMN_NAME| COLUMN_POSITION| DESCEND| TYPE| XTYPE| FLAG|| 33555474| INDEX33555474| ID| 1| ASC| BT| 17| 5|CREATE OR REPLACE INDEX "SYSDBA"."IX_TEST_LEFT02" ON "SYSDBA"."TEST_LEFT02"("ID" ASC,"C1" ASC) STORAGE(ON "MAIN", CLUSTERBTR) ;| ID| INDEX_NAME| COLUMN_NAME| COLUMN_POSITION| DESCEND| TYPE| XTYPE| FLAG|| 33555475| IX_TEST_LEFT02| ID| 1| ASC| BT| SEC| 0|| 33555475| IX_TEST_LEFT02| C1| 2| ASC| BT| SEC| 0|##### TABLE STATS INFO : SYSDBA.TEST_LEFT01 STATISTICS IS NULL.##### TABLE STATS INFO : SYSDBA.TEST_LEFT02 STATISTICS IS NULL.###################################################################################################################################################### SQL PLAN INFO :| SEQ| DEP|SQL_PLAN || 1| 0|#NSET2: [2,337,148]; CPU_COST:0; IO_COST:2 || 2| 1| #PRJT2: [2,337,148]; CPU_COST:0; IO_COST:2 || 3| 2| #NEST LOOP INDEX JOIN2: [2,337,148]; CPU_COST:0; IO_COST:2 || 4| 3| #SSCN: [1,337,52]; IX_TEST_LEFT01[is_global(0)](TEST_LEFT01 AS A); CPU_COST:0; IO_COST:1 || 5| 3| #BLKUP2: [2,1,48]; INDEX33555474(TEST_LEFT02 AS B); CPU_COST:2; IO_COST:0 || 6| 4| #SSEK2: [2,1,48]; SCAN_TYPE(ASC); INDEX33555474[is_global(0)](TEST_LEFT02 AS B); SCAN_RANGE[A.ID,A.ID]; CPU_COST:2; IO_COST:0|######################################################################################################### SQL ET INFO :| OP| TIME(MS)|PERCENT| RANK| SEQ|N_ENTER| MEM(KB)| DISK(KB)| HASH_CELLS| HASH_CONFLICT|| DLCK| 0.03| 0.07%| 7| 0| 3| 0| 0| 0| 0|| SSCN| 0.12| 0.24%| 6| 4| 3| 0| 0| 0| 0|| NSET2| 6.62| 13.00%| 5| 1| 340| 0| 0| 0| 0|| PRJT2| 7.28| 14.30%| 4| 2| 676| 0| 0| 0| 0|| IJI2| 10.45| 20.51%| 3| 3| 1015| 0| 0| 0| 0|| SSEK2| 11.01| 21.62%| 2| 6| 674| 0| 0| 0| 0|| BLKUP2| 15.41| 30.26%| 1| 5| 1348| 0| 0| 0| 0|DMSQL executed successfullyused time: 75.953(ms). Execute id is 69804.
阅读原文:https://mp.weixin.qq.com/s/nEDBznM2nsZxfEX2WRFrlw
该文章在 2026/4/27 15:40:28 编辑过