现场环境
系统移植,上线前压测。
问题现象
压测时CPU使用率超过5000%(8核CPU)。
需求描述
通过系统视图取一张表的列名、字段类型、字段是否可为空、字段默认值以及是否是主键。
处理方法
原始SQL:
select a.column_name,
data_type,
DECODE (nullable,
'Y', 0,
1) notnull,
data_default,
DECODE (A .column_name,
b.column_name,1,0) pk
from all_tab_columns a,(select column_name
from all_constraints c,
all_cons_columns col
where c.constraint_name = col.constraint_name
and c.constraint_type = 'P'
and c.table_name = 'T1' and c.OWNER='SYSDBA') b
where table_name = 'T1' and a.OWNER='SYSDBA'
and a.column_name = b.column_name (+)
注:原始SQL其实有问题,少了and c.OWNER='SYSDBA'条件,这样多个模式下有同样表名的话结果就错了。
原始SQL执行计划:
(计划太长放不下,大家可以直接看这个SQL的计划。)
我们可以看到,原始SQL计划有494行,压测时执行耗时500ms以上,导致CPU使用率无法下降。
优化思路:
因为原始SQL中用到的all_tab_columns、all_constraints和all_cons_columns都是兼容Oracle做的,不是DM自带的视图,思路就是使用达梦自带的系统视图来查询,主要是SYSCONS、SYSINDEXES、SYSCOLUMNS、SYSOBJECTS这几个视图。
但是这里面有个问题,
通过syscons、sysindexes和sysobjects关联可以获取的约束名字,但是获取列名的时候关联syscolumns,这个无法和约束的列名关联起来。
通过all_cons_columns视图查询。
select * from all_cons_columns;
(计划不放,大家自己看)
分析这条SQL的执行计划,可以看到这个视图用到SYSCONS、SYSINDEXES、SYSCOLUMNS、SYSOBJECTS这几个视图,但是关联条件还是无法确定,无法获取某一列是否是索引列。
打开SQL日志,通过manager查看表结构,发现要用到一个函数SF_COL_IS_IDX_KEY(INDS.KEYNUM, INDS.KEYINFO, COLS.COLID)
结果为1才是索引列,如此修改原始SQL就方便了。
修改后SQL:
select o.name table_Name,o3.name owner,cols.name column_name,cols.TYPE$ data_type,DECODE (cols.nullable$,'Y', 0,1) notnull,
cols.defval data_default,
decode(con.type$,'P',SF_COL_IS_IDX_KEY(I.KEYNUM, I.KEYINFO, COLS.COLID),0) PK
from sysobjects o
left join SYSCONS con on o.id = con.tableid and con.type$='P'
LEFT JOIN sysobjects o3 on o.schID=o3.ID
left join SYSINDEXES i on con.indexid = i.id
LEFT JOIN SYSCOLUMNS cols on O.ID=COLS.ID --AND O2.PID=COLS.ID
where o.name = 'T1' AND O3.NAME='SYSDBA';
修改后再压测,发现CPU已下降,问题解决。
经验分享
遇到类似问题,首先要想到的是改兼容性视图为DM自带视图SYSCONS、SYSINDEXES、SYSCOLUMNS、SYSOBJECTS等这几个视图,具体看dba手册,然后根据某个视图查询,再根据执行计划等多方面分析。
关键点:
需要通过一个函数SF_COL_IS_IDX_KEY(INDS.KEYNUM, INDS.KEYINFO, COLS.COLID),结果为1才是索引列。之前把dba视图看烂了也没找到索引和列对应的关系,折腾好久才通过SQL日志定位到。
文章
阅读量
获赞