性能分析需从三个核心维度逐层排查,定位问题根源:
聚焦 CPU、内存、I/O 等基础资源使用情况,常用监控工具及作用如下:
•
top:实时监控 CPU 使用率与进程状态,按Shift+P可按 CPU 使用率排序。
指标分类 | 关键指标 | 含义解读(结合数据库性能分析场景) | 示例数据 |
---|---|---|---|
系统基础 | 时间 | 当前系统时间,用于定位性能问题发生时刻 | 15:00:08 |
负载平均值 | 过去 1/5/15 分钟系统平均负载,反映整体压力(如>CPU 核心数需警惕) | load average: 0.06, 0.06, 0.08 | |
CPU 核心 | % Cpu(s) 核心占比 | us(用户态,数据库进程常用)、sy(内核态,I/O 等消耗)<br>理想比例:us > sy,sy 持续高表明系统调用过多 | %Cpu(s): 0.3 us, 0.5 sy |
内存核心 | 总内存 / 已用 / 可用 | 物理内存总量、已占用(含缓存)、实际可分配给数据库的量<br>当可用内存 < 10% 总内存时需预警 | Mem: 2884.3 total / 1597.2 used / 274.5 avail |
交换空间 | 已用 Swap | 虚拟内存使用量(过高可能引发数据库性能波动)<br>Swap使用率 > 20% 会导致显著性能下降 | Swap used: 3342.6 |
进程关键 | PID + COMMAND | 进程 ID 与名称(重点关注 dmserver 等数据库进程) | PID 309756(dmserver) |
% CPU(进程) | 单个进程 CPU 占用(如 dmserver 持续 > 80% 需排查 SQL 或索引问题) | dmserver: 0.3% CPU | |
% MEM(进程) | 进程内存占用(数据库进程内存不足会触发磁盘交换)<br>持续增长可能预示内存泄漏 | dmserver: 0.1% MEM |
内存 avail 过低且 Swap 高用,说明物理内存紧张,可能导致数据库缓存失效、性能下降。
•
iostat/dstat:分析磁盘 I/O 使用情况,前者可查看读写速率等指标,后者能更直观地收集 CPU、I/O 等信息并每秒刷新。
指标分类 | 关键指标 | 含义解读(结合数据库场景) | 示例数据 |
---|---|---|---|
CPU 关联 | %iowait | CPU 等待磁盘 I/O 完成的时间占比,高值说明磁盘慢 | 0.28% |
磁盘设备 | Device | 磁盘设备名(如 sda 是系统盘 / 数据库盘需关注) | sda、loop0 |
tps | 每秒向磁盘发起的 I/O 请求数(数据库读写压力) | sda: 105.05 | |
kB_read/s | 每秒从磁盘读取的数据量(读性能瓶颈参考) | sda: 1799.14 KB/s | |
kB_wrtn/s | 每秒向磁盘写入的数据量(写性能瓶颈参考) | sda: 711.82 KB/s |
场景化分析:
•若 %iowait 持续>10% + sda 的 tps 高,说明数据库所在磁盘 I/O 拥堵,可能导致 SQL 执行变慢(如查询需读磁盘、事务写落盘延迟);
•若 kB_read/s 长期接近磁盘最大读速,需检查数据库是否有大量全表扫描(没走索引),或考虑升级存储(SSD 替换机械盘)。
核心用于快速判断 “磁盘 I/O 是否拖慢数据库” ,抓住磁盘读写请求、吞吐量、CPU 等待这几个核心点即可初步排查 。
•free:查看内存使用情况,了解已用、空闲及缓存内存等数据。
•nmon:用于长期监控系统整体资源情况,例如执行./nmon -f -t -s 10 -c 1435可实现持续 8 小时、每 10 秒采集一次数据的监控。
•perf top:定位系统热点函数,如libdmdta.50中的高频操作,辅助找到性能瓶颈底层原因。
•使用 vmstat 命令对磁盘 I/O 性能进行分析:
[root@dm8 ~]# vmstat 1 5
如果 b 的值为 2~3 倍 CPU 数量,bi 和 bo 的值很大(有时 bi 和 bo 值很小,但 in 和 cs 很大,也会引起磁盘 IO 负载重),wa 的值持续很高,如高于 40,id 也持续高于 70,这些现象都表明系统的 IO 可能出现性能问题。
可以进一步通过 iostat 命令分析,如下所示:
结果分析
检查 %util(服务 IO 的时间占总时间的百分比),如果这个值接近 100%,表示 IO 的请求很多(表示任务服务的所有时间几乎都用在 IO 上),这种现象表明磁盘 IO 性能出现瓶颈。
检查r_await(读请求平均等待 + 处理耗时)、w_await(写请求平均等待 + 处理耗时 )这些细分指标的,传统的 await(整体 I/O 请求平均耗时)可通过 r_await、w_await 结合读写比例大致推算,或者理解为这里用细分的读写等待来呈现更细粒度的 I/O 延迟情况。
检查aqu-sz:表示 IO 排队的现象,如果排队过长会影响 IO 的响应时间。
r/s+w/s:可以计算当前系统的 iops(可以结合硬盘的测试或者硬件参数来衡量是否超过磁盘的 iops 最大值)。
通过 iostat 了解到如果磁盘 I/O 出现性能瓶颈,可以借助 pidstat ,定位出导致瓶颈的进程,分析进程的 I/O 行为,结合应用程序的原理,分析这些 I/O 的来源。
网络性能对数据库也有很大的影响,数据库服务器和 Web 服务器之间会进行网络传输,网络延迟和带宽大小都是影响因素。
相关命令:ifconfig
ifconfig 是 linux 中用于显示或配置网络设备(网络接口卡)的命令。在某系统中输入此命令后显示结果如下所示:
ifconfig
ethtool ens33
结果解读:
Supported link modes 为网卡支持的连接模式。
speed 和 duplex 字段为当前网络速率和模式。
分析方法
使用 ping 命令测试网络的连通性和响应时间。
ping 发送 ICMP echo 数据包来探测网络的连通性,除了能直观地看出网络的连通状况外,还能获得本次连接的往返时间(RTT 时间),丢包情况,以及访问的域名所对应的 IP 地址(使用 DNS 域名解析)。
ping -c 4 baidu.com
##参数 -c 表示指定发包数。
解析 ping baidu.com 结果
执行 ping -c 4 baidu.com ,解析到百度某台服务器的 IP 地址为 182.61.201.211 。
RTT(往返时间)相关统计:
最小 RTT(rtt min):6.839 ms
平均 RTT(rtt avg):10.783 ms
最大 RTT(rtt max):20.902 ms
算术平均差(rtt mdev,反映延迟波动程度 ):5.853 ms
解析 ping 10.127.17.131 结果(补充说明 )
执行 ping -c 4 10.127.17.131 ,目标为内网 IP 10.127.17.131 ,其 RTT 统计:
最小 RTT:0.043 ms
平均 RTT:2.604 ms
最大 RTT:10.230 ms
算术平均差:4.402 ms
从架构、参数和会话三个方面优化数据库运行状态:
•架构优化:根据业务类型选择合适架构,事务型业务采用读写分离,分析型业务采用 MPP 集群。
•参数调优(关键参数示例):
•会话监控:
◦查看活跃会话:SELECT COUNT(*) FROM VSESSIONS WHERE STATE='ACTIVE'。
◦分析阻塞查询:通过VLOCK和V$SESSIONS关联查询,定位阻塞源头。
下载安装DMLOG工具
[dmdba@dameng DMLOG8.181]$ vi dmlog.properties
[root@dm8 DMLOG8.181]# java -jar Dmlog_DM_8.18.jar
运行过程如下图所示,执行完成后会按当前时间生成对应 RESULT_$DATE 文件夹,并将所有统计信息都存放该目录中。
的 RESULT_$DATE 结果文件夹下有根据配置的执行时间和执行次数上限值命名的 excel 文件(xls)、报错的 SQL 文件(txt)、长度超过 30000 的 SQL 文件 (txt),echart 散点图及 90% 平均次数和平均耗时的 SQL 统计图 (html)。
SP_SET_PARA_VALUE(1,'SVR_LOG',1);
配置数据文件目录下的 sqllog.ini 文件。
如果对 sqllog.ini 进行了修改,可通过调用以下函数即时生效,无需重启数据库。
SP_REFRESH_SVR_LOG_CONFIG();
配置成功以后可以通过
sqllog.ini 文件配置成功后可在 dmsql 指定目录下生成 dmsql 开头的 log 日志文件。日志内容如下所示
执行
[root@dm8 DMLOG8.181]# nohup java -jar -Xms256m -Xmx4096m Dmlog_DM_8.18.jar > ./sql_realtime_parse2.log 2>&1 &
简单来说,执行计划就是一条 SQL 语句在数据库中的执行过程或访问路径的描述。SQL 语言是种功能强大且非过程性的编程语言,比如以下这条 SQL 语句:
EXPLAIN SELECT * FROM ADMINS;
执行计划的每行即为一个计划节点,主要包含三部分信息。
第一部分 NEST2、PRJT2、CSCN2 为操作符及数据库具体执行了什么操作。
第二部分的三元组为该计划节点的执行代价,具体含义为[代价,记录行数,字节数]。
第三部分为操作符的补充信息。
例如:第三个计划节点表示操作符是 CSCN2(即全表扫描),代价估算是 1 ms,扫描的记录行数是 1行,输出字节数是 125个。
各计划节点的执行顺序为:缩进越多的越先执行,同样缩进的上面的先执行,下面的后执行,上下的优先级高于内外。缩进最深的,最先执行;缩进深度相同的,先上后下。口诀:最右最上先执行。
达梦数据库可通过两种方式查看执行计划。
方式一:通过 DM 数据库配套管理工具查看。
方式二:使用 explain 命令查看。
以下对两种查看方式进行介绍。
在 DM 配套管理工具中,选中待查看执行计划的 SQL 语句,点击工具栏中的按钮,或使用快捷键 F9,即可查看执行计划。
在待查看执行计划的 SQL 语句前加 explain 执行 SQL 语句即可查看预估的执行计划:
EXPLAIN SELECT * FROM TEST2;-- 文本模式查看执行计划
(3)使用 disql 命令行查真实执行计划
set autotrace traceonly
SELECT * FROM TEST2;
重点关注 logical reads(逻辑读)和 physical reads(物理读)相应的指标值,并结合 rows processed 返回处理行数多少来分析。如果返回行数少(并且 bytes sent to client 总量不大),应尽可能减少 IO 开销,让执行计划选择正确的索引路径。 Sort(disk) 一般因排序( hash join 发生归并、order by、group by 场景)区内存不足,如果数据库服务器物理内存充足,可以适当上调排序区内存,尽量避免操作刷盘,否则会影响执行性能。
•关键操作符及含义:
EXPLAIN SELECT * FROM TEST2;-- 文本模式查看执行计划
EXPLAIN SELECT * FROM TEST2;
1.NSET 是用于结果集收集的操作符,一般是查询计划的顶层节点,优化工作中无需对该操作符过多关注,一般没有优化空间。
2. PRJT:投影
PRJT 是关系的【投影】 (project) 运算,用于选择表达式项的计算。广泛用于查询,排序,函数索引创建等。优化工作中无需对该操作符过多关注,一般没有优化空间。
3.CSCN:全表扫描
CSCN2 是 CLUSTER INDEX SCAN 的缩写即通过聚集索引扫描全表,全表扫描是最简单的查询,如果没有选择谓词,或者没有索引可以利用,则系统一般只能做全表扫描。全表扫描 I/O 开销较大,在一个高并发的系统中应尽量避免全表扫描。
ET 工具是 DM 数据库自带的 SQL 性能分析工具,能够统计 SQL 语句执行过程中每个操作符的实际开销,为 SQL 优化提供依据以及指导。
--两个参数均为动态参数,可直接调用系统函数进行修改 SP_SET_PARA_VALUE(1,'ENABLE_MONITOR',1); SP_SET_PARA_VALUE(1,'MONITOR_SQL_EXEC',1);
--会话级别修改只在当前会话生效 SF_SET_SESSION_PARA_VALUE('MONITOR_SQL_EXEC',1);
--关闭 ET
SP_SET_PARA_VALUE(1,'ENABLE_MONITOR',0); SP_SET_PARA_VALUE(1,'MONITOR_SQL_EXEC',0);
2.查看方式
点击执行号即可打开ET查看
ET 结果说明:
OP: 操作符
TIME(us): 时间开销,单位为微秒
PERCENT: 执行时间占总时间百分比
RANK: 执行时间耗时排序
SEQ: 执行计划节点号
N_ENTER: 进入次数
当看到CSCN2操作符,说明进行了全表扫描,向上寻找SLCT2操作符,给SLCT2中的过滤条件增加索引可以消除全表扫描。通过消除全表扫描可以解决大部分的sql性能问题。
关键问题分析:
CSCN2(全表扫描)占比77.20% - 主要性能瓶颈
SLCT2(内存过滤)占比4.3% - 在内存中过滤条件
查看执行计划
创建合适的索引
CREATE INDEX IDX_STUDENT_NAME ON STUDENT_SCORES(STUDENT_NAME);
CREATE INDEX IDX_COURSE_SCORE ON STUDENT_SCORES(COURSE, SCORE);
创建复合覆盖索引
CREATE INDEX IDX_COURSE_SCORE_COVER
ON STUDENT_SCORES(COURSE, SCORE, STUDENT_NAME);
从单字段到复合、再到覆盖索引,执行步骤的耗时分布和占比逐步变化,覆盖索引更贴合 “索引即数据” 的查询场景,减少了额外 IO,适合需要多字段过滤或返回的查询。可根据实际查询语句(如 WHERE 条件、SELECT 字段)选择对应索引优化性能。
– 低效查询:全表扫描+哈希分组
EXPLAIN
SELECT department, COUNT(*), AVG(salary)
FROM adm
GROUP BY department;
执行计划分析:
1 #NSET2: [10, 1, 86]
2 #PRJT2: [10, 1, 86]
3 #HAGR2: [10, 1, 86]; grp_num(1) -- 哈希分组
4 #CSCN2: [1, 10000, 86] -- 全表扫描
– 高效查询:索引扫描+有序分组
EXPLAIN
SELECT /*+ USE_SAGR_GROUP */
department, COUNT(*), AVG(salary)
FROM adm
GROUP BY department; -- 部门字段已建索引
优化后执行计划:
1 #NSET2: [10, 1, 86]
2 #PRJT2: [10, 1, 86]
3 #SAGR2: [10, 1, 86]; grp_num(1) -- 有序分组
4 #SSCN: [1, 10000, 86] -- 索引扫描(IDX_ADMIN_DEPT)
– 低效:先分组后过滤
EXPLAIN
SELECT department, AVG(salary)
FROM adm
GROUP BY department
HAVING AVG(salary) > 6000;
在执行 GROUP BY department 时,数据库需要对 adm 表中的所有数据进行分组操作。然后,再对分组后的结果使用 HAVING AVG(salary) > 6000 进行过滤。这意味着数据库要先处理表中全部数据来完成分组聚合计算(如计算每个部门的平均薪资 ),即使最终很多分组结果是要被过滤掉的。
例如,假设 adm 表中有 10 万条数据,涉及 100 个部门,数据库要先对这 10 万条数据进行分组,计算出 100 个部门的平均薪资, 然后再过滤掉不符合条件的部门, 若大部分部门平均薪资都不超过 6000,那么前面大量的分组计算其实是做了 “无用功”。
– 高效:先过滤后分组
EXPLAIN
SELECT /*+ INDEX(admin IDX_ADMIN_SAL_DEPT) */
department, AVG(salary)
FROM adm
WHERE salary > 6000 -- 利用复合索引
GROUP BY department;
– 低效:无序分组
EXPLAIN
SELECT department, access_level, COUNT(*)
FROM admin
GROUP BY department, access_level;
– 高效:有序分组
创建的 IDX_ADMIN_DEPT_LEVEL (department, access_level) 复合索引与 GROUP BY 的字段顺序完全匹配
CREATE INDEX IDX_ADMIN_DEPT_LEVEL ON adm(department, access_level);
EXPLAIN
SELECT /*+ USE_SAGR_GROUP */
department, access_level, COUNT(*)
FROM adm
GROUP BY department, access_level; -- 复合索引字段
用二级索引扫描替代聚簇 / 全表扫描,索引数据量小,读磁盘页数少,速度更快。
现在是 SECOND INDEX SCAN(二级索引扫即 IDX_ADMIN_DEPT_LEVEL),直接通过创建的复合索引扫描。因为索引仅包含 department、access_level 及索引键,数据量更小,扫描更快。
-- 执行查询(索引未生效)
EXPLAIN SELECT * FROM ETEST.EMPLOYEES WHERE SALARY > 8000;
收集统计信息
-- 收集EMPLOYEES表统计信息
DBMS_STATS.GATHER_TABLE_STATS(
'ETEST',
'EMPLOYEES',
ESTIMATE_PERCENT => 100, -- 全量收集
METHOD_OPT => 'FOR ALL INDEXED COLUMNS SIZE AUTO'
);
– 查看表统计信息
-- 表统计
DBMS_STATS.TABLE_STATS_SHOW('ETEST', 'EMPLOYEES');
未走索引,是数据量小导致之一
-- 列统计
DBMS_STATS.COLUMN_STATS_SHOW('ETEST', 'EMPLOYEES', 'SALARY');
--LOW_VALUE:列的最小值,为 3004.28 ,即最低是 3004.28 。
HIGH_VALUE:列的最大值,为 9998.54 ,即最高接近 10000 。
NUM_NULLS:列的空值数量,这里是 0 ,说明 SALARY 列没有空值。
NUM_BUCKETS:直方图的桶数量,为 1000 ,表示统计信息用 1000 个桶来描述数据分布(因 NUM_DISTINCT 是 1000,可能是等频或等值直方图 )。
SAMPLE_SIZE:统计信息采样的行数,为 1000 ,说明是对全表(1000 行)做了统计,统计结果精准。
表只有 1000 行,即使过滤后有 200 行左右符合条件(估算 ),全表扫描 1000 行的成本(读 32 个数据块 ),比走索引(扫描索引块 + 回表取数据 )的成本更低。优化器基于这些统计信息,判断全表扫描更高效,所以没选索引。
– 索引统计
DBMS_STATS.INDEX_STATS_SHOW('ETEST', 'IDX_EMP_SALARY');
清理执行计划缓存
-- 查找问题SQL缓存项
SELECT cache_item, sqlstr
FROM v$cachepln
WHERE sqlstr LIKE 'SELECT * FROM ETEST.EMPLOYEES%';
– 清理缓存(cache_item=140183402600088)
CALL sp_clear_plan_cache(140183402600088);
HINT 说明
1、SF_INJECT_HINT函数
提供无需修改 SQL 语句但依然能按照指定的 HINT 运行语句的相关功能,使用时有以下限制:
2、SQL语句指定HINT
需要在SQL语句中指定HINT,如果 HINT 的语法没有写对或指定的值不正确,DM 并不会报错,而是直接忽略 HINT 继续执行。
SF_INJECT_HINT(‘sql语句’, ‘参数名(参数值)’, ‘规则名’, null,TRUE,TRUE);
**对指定 SQL 撤回已增加的 HINT** ```SQL SF_DEINJECT_HINT('规则名'); 修改已指定 HINT 的规则属性 SF_ALTER_HINT('('规则名', 'STATUS', 'DISABLED');
在不改动原 SQL 时,可使用ENABLE_RQ_TO_NONREF_SPL(3)参数优化,
相关说明如下:
•该参数用于将相关查询表达式转化为非相关查询表达式,使相关查询表达式的执行处理由之前的平坦化方式转化为一行处理。
•取值含义:
•0 表示不启用该优化;
•1 表示对查询项中出现的相关子查询表达式进行优化处理;
•2 表示对查询项和 WHERE 表达式中出现的相关子查询表达式进行优化处理;
•4 表示相关查询采用 SPL 方式去相关性后,可作为单表过滤条件。支持组合值,
•如 3 表示同时进行 1 和 2 的优化。
开启该参数
SELECT SF_GET_PARA_VALUE(1, 'ENABLE_INJECT_HINT');
SP_SET_PARA_VALUE(1, ‘ENABLE_INJECT_HINT’, 1);
原始SQL执行
-- 原始SQL(不带优化参数)
SELECT
s.student_id,
s.name,
s.class_id,
(SELECT AVG(grade) FROM student_courses sc WHERE sc.student_id = s.student_id) AS avg_grade,
(SELECT COUNT(*) FROM student_courses sc WHERE sc.student_id = s.student_id AND grade >= 90) AS excellent_count,
(SELECT c.course_name FROM courses c WHERE c.course_id =
(SELECT sc.course_id FROM student_courses sc
WHERE sc.student_id = s.student_id
ORDER BY sc.grade DESC LIMIT 1)
) AS best_course
FROM students s
WHERE s.department = '计算机'
AND s.class_id IN ('CLASS2', 'CLASS3', 'CLASS4');
消耗208毫秒
带优化参数的SQL执行
-- 带优化参数的SQL
SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(3) */
s.student_id,
s.name,
s.class_id,
(SELECT AVG(grade) FROM student_courses sc WHERE sc.student_id = s.student_id) AS avg_grade,
(SELECT COUNT(*) FROM student_courses sc WHERE sc.student_id = s.student_id AND grade >= 90) AS excellent_count,
(SELECT c.course_name FROM courses c WHERE c.course_id =
(SELECT sc.course_id FROM student_courses sc
WHERE sc.student_id = s.student_id
ORDER BY sc.grade DESC LIMIT 1)
) AS best_course
FROM students s
WHERE s.department = '计算机'
AND s.class_id IN ('CLASS2', 'CLASS3', 'CLASS4');
–消耗162毫秒
对指定 SQL 增加 HINT 注入的命令:
-- 启用HINT注入功能
SP_SET_PARA_VALUE(1, 'ENABLE_INJECT_HINT', 1);
-- 注入优化HINT
SF_INJECT_HINT('SELECT s.student_id, s.name, s.class_id, (SELECT AVG(grade) FROM student_courses sc',
'ENABLE_RQ_TO_NONREF_SPL(3)',
'学生成绩查询优化',
null, TRUE, TRUE);
-- 查询已注入的HINT
SELECT * FROM SYSINJECTHINT WHERE NAME = '学生成绩查询优化';
--通过SF_INJECT_HINT函数注入的优化规则已生效
-- 执行带注入HINT的SQL(无需修改原SQL)
SELECT
s.student_id,
s.name,
s.class_id,
(SELECT AVG(grade) FROM student_courses sc WHERE sc.student_id = s.student_id) AS avg_grade,
(SELECT COUNT(*) FROM student_courses sc WHERE sc.student_id = s.student_id AND grade >= 90) AS excellent_count,
(SELECT c.course_name FROM courses c WHERE c.course_id =
(SELECT sc.course_id FROM student_courses sc
WHERE sc.student_id = s.student_id
ORDER BY sc.grade DESC LIMIT 1)
) AS best_course
FROM students s
WHERE s.department = '计算机'
AND s.class_id IN ('CLASS2', 'CLASS3', 'CLASS4');
--消耗152毫秒
可通过视图查询:select * from SYSINJECTHINT;
--查看原始SQL执行计划
EXPLAIN
SELECT
s.student_id,
s.name,
s.class_id,
(SELECT AVG(grade) FROM student_courses sc WHERE sc.student_id = s.student_id) AS avg_grade,
(SELECT COUNT(*) FROM student_courses sc WHERE sc.student_id = s.student_id AND grade >= 90) AS excellent_count,
(SELECT c.course_name FROM courses c WHERE c.course_id =
(SELECT sc.course_id FROM student_courses sc
WHERE sc.student_id = s.student_id
ORDER BY sc.grade DESC LIMIT 1)
) AS best_course
FROM students s
WHERE s.department = '计算机'
AND s.class_id IN ('CLASS2', 'CLASS3', 'CLASS4');
--查看优化后SQL执行计划
EXPLAIN
SELECT /*+ ENABLE_RQ_TO_NONREF_SPL(3) */
s.student_id,
s.name,
s.class_id,
(SELECT AVG(grade) FROM student_courses sc WHERE sc.student_id = s.student_id) AS avg_grade,
(SELECT COUNT(*) FROM student_courses sc WHERE sc.student_id = s.student_id AND grade >= 90) AS excellent_count,
(SELECT c.course_name FROM courses c WHERE c.course_id =
(SELECT sc.course_id FROM student_courses sc
WHERE sc.student_id = s.student_id
ORDER BY sc.grade DESC LIMIT 1)
) AS best_course
FROM students s
WHERE s.department = '计算机'
AND s.class_id IN ('CLASS2', 'CLASS3', 'CLASS4');
-- 删除注入的HINT
SF_DEINJECT_HINT('学生成绩查询优化');
-- 确认HINT已被删除
SELECT * FROM SYSINJECTHINT WHERE NAME = '学生成绩查询优化';
达梦社区地址https://eco.dameng.com
文章
阅读量
获赞