首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >达梦数据库性能优化

达梦数据库性能优化

作者头像
收心
发布2025-04-08 09:15:08
发布2025-04-08 09:15:08
84500
代码可运行
举报
文章被收录于专栏:Java实战博客Java实战博客
运行总次数:0
代码可运行

正文先获取硬件信息获取达梦基本信息vlicens 优先排查 MAX_CPU_NUM查看达梦内存分配状态dual 方式一v sysstat 方式二:正在执行的SQL统计不同账号连接的数量慢SQL排查查看缓冲池命中率内存分配查看死锁杀死 Session查询历史死锁查看当前活跃的会话消耗的内存统计信息(提升很有效)统计信息概述收集统计信息手动收集自动收集查看统计信息更新统计信息删除统计信息

近期遇到生产数据库机器响应特别慢的场景。特别翻了达梦的文档。官方说的内容太多了,做点小总结,快速定位问题。一些工具可能比较好用可参考(我理解为运维实施的范畴,也不应该由开发人员随便操作生产环境):https://eco.dameng.com/document/dm/zh-cn/ops/tool-monitor.html

官方链接参考:

安装前对数据库有对应规划:https://eco.dameng.com/document/dm/zh-cn/ops/before-installation.html# 比如磁盘性能:参考:

性能诊断:https://eco.dameng.com/document/dm/zh-cn/ops/performance-diagnosis.html

性能优化:https://eco.dameng.com/document/dm/zh-cn/ops/performance-optimization.html

sql执行计划分析:https://cloud.tencent.com/developer/article/2496574

正文

先获取硬件信息

  1. 硬件信息收集项。

硬件

硬件配置(命令)

运行情况(命令)

CPU

cat /proc/cpuinfo

top\vmstat\sar

内存

cat /proc/meminfo

top\vmstat\free

磁盘

RAID

iostat

网络

ifconfig

ping\route\netstat

不同Linux操作系统,可能命名不一定都齐全。无所谓,能看多少看多少。

看下磁盘压力 iostat -xmd

参考:参数讲解:http://linux.zanglikun.com/c/iostat.html

代码语言:javascript
代码运行次数:0
运行
复制
[root@VM-4-14-centos ~]# iostat -xmd
Linux 3.10.0-1160.81.1.el7.x86_64 (VM-4-14-centos)      2025年04月07日  _x86_64_        (4 CPU)

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
vda               0.03    14.74    2.58   16.61     0.06     0.36    45.39     0.05    2.69    3.94    2.50   0.90   1.74
scd0              0.00     0.00    0.00    0.00     0.00     0.00     7.20     0.00    0.46    0.46    0.00   0.46   0.00

获取达梦基本信息

查看达梦版本信息

代码语言:javascript
代码运行次数:0
运行
复制
SELECT * FROM V$VERSION LIMIT 100;

输出

代码语言:javascript
代码运行次数:0
运行
复制
DM Database Server 64 V8
8.1
安全版
DB Version: 0x7000c
0XXXXXXXXX-20240712-234979-20093
Msg Version: 0
Gsu level(3-4) cnt: 3
Gsu level(5) cnt: 0

其他重要的排查信息

代码语言:javascript
代码运行次数:0
运行
复制
会话数:	SELECT COUNT(*) FROM V$SESSIONS LIMIT 10;
事务数:	SELECT COUNT(*) FROM V$TRX LIMIT 10;
等待事件:SELECT * FROM V$TRXWAIT LIMIT 100;
内存池:	SELECT * FROM V$MEM_POOL LIMIT 100;

v$licens 优先排查 MAX_CPU_NUM

DATE_GEN:数据库安装时间

EXPIRED_DATE:证书过期时间

MAX_CPU_NUM:可使用最大核心数

代码语言:javascript
代码运行次数:0
运行
复制
-- 关注MAX_CPU_NUM。这个可能会出现“一核有难,7核观战”的情况
SELECT * FROM v$license LIMIT 100;

查看达梦内存分配状态

dual 方式一

代码语言:javascript
代码运行次数:0
运行
复制
-- 总内存由 “系统缓冲区大小”与“共享内存池大小”共同组成。两者任意过大,都对整体性能影响很大。建议均衡配置。
-- BUFFER_SIZE:系统缓冲区大小,以 M 为单位。推荐值:系统缓冲区大小为可用物理内存的 60%~80%。有效值范围(8~1048576)。
-- MEM_POOL:共享内存池大小,以 M 为单位。共享内存池是由 DM 管理的内存。有效值范围:32 位平台为(642000),64 位平台为(6467108864)。
-- TOTAL_SIZE:BUFFER_SIZE 和 MEM_POOL 的总和。

SELECT
	(SELECT SUM(n_pages) * PAGE()/1024/1024 FROM v$bufferpool)||'MB' AS 系统缓冲区大小,
	(SELECT SUM(total_size)/1024/1024 FROM v$mem_pool)||'MB' AS 共享内存池大小,
	(SELECT SUM(n_pages) * PAGE()/1024/1024 FROM v$bufferpool)+(SELECT SUM(total_size)/1024/1024 FROM v$mem_pool)||'MB' AS 总内存大小TOTAL_SIZE
FROM DUAL LIMIT 10;

v$sysstat 方式二:

代码语言:javascript
代码运行次数:0
运行
复制
SELECT name, stat_val/1024.0/1024.0 FROM v$sysstat where CLASSID=11 LIMIT 10; 

查询结果中,字段含义如下:

  • memory pool size in bytes:内存池总的大小。
  • memory used bytes:内存池使用的内存大小。
  • memory used bytes from os:内存池从操作系统分配的大小。

正在执行的SQL

查看正在执行的SQL

代码语言:javascript
代码运行次数:0
运行
复制
-- 查询当前连接的信息。
SELECT
    SYSDATE                    AS "当前时间,非字段",
	USER_NAME                  AS "连接的账号",
    STATE                      AS "状态",
    SF_GET_SESSION_SQL(SESS_ID) AS "完整SQL",
    SESS_ID                    AS "会话 ID,会话唯一标识",
    SESS_SEQ                   ,
    --SQL_TEXT                 ,
    SEQ_NO                     ,
    TRX_ID                     AS "事务号",
    CREATE_TIME                ,
    CLNT_IP                    AS "客户端IP"
--    CLNT_HOST                  AS "客户端主机名",
--    APPNAME                    AS "客户端名称",
--    OSNAME                     AS "客户端操作系统"
FROM 
    v$sessions 
WHERE 
    STATE IN ('ACTIVE', 'WAIT') LIMIT 100;
    
-- STATE有:ACTIVE=活跃的、WAIT=等待的、IDLE=闲置的。因为各种应用都会配备数据库连接池,就会有很多IDLE的连接。所以排查问题就不查询IDLE的状态了。

统计不同账号连接的数量

代码语言:javascript
代码运行次数:0
运行
复制
-- 统计不同账号连接的数量
SELECT
    STATE AS "状态",
    USER_NAME AS "连接的账号",
    COUNT(1) AS "数量"
FROM
    v$sessions
GROUP BY
    STATE,USER_NAME
LIMIT 100
;

慢SQL排查

代码语言:javascript
代码运行次数:0
运行
复制
-- 慢日志记录信息
SELECT
    SESS_ID AS "会话 ID,会话唯一标识",
    -- SQL_ID AS "语句 ID,语句唯一标识",
    SQL_TEXT AS SQL文本,
    EXEC_TIME AS "执行时间(毫秒)",
    FINISH_TIME AS "执行结束时间",
    N_RUNS AS "执行次数",
    SEQNO AS "编号",
    TRX_ID AS "事务号"
FROM 
    V$LONG_EXEC_SQLS
LIMIT 100;

查看缓冲池命中率

代码语言:javascript
代码运行次数:0
运行
复制
SELECT
      NAME AS "缓冲池名称",
      SUM(PAGE_SIZE) * SF_GET_PAGE_SIZE / 1024 / 1024 AS "缓冲池大小_MB",
      SUM(RAT_HIT) / COUNT(*) AS "命中率"
FROM
      v$bufferpool
GROUP BY NAME LIMIT 100;       
  • KEEP: 适合存储频繁访问的数据,命中率为1,表明非常有效。
  • RECYCLE: 适合不太频繁访问的数据,命中率较高但不如 KEEP。
  • FAST: 设计用于快速访问,命中率几乎为1,表现优秀。
  • NORMAL: 用于常规数据访问,命中率较高,但可以进一步优化。
  • ROLL: 用于存储回滚信息,命中率为1,确保事务的完整性。

内存分配

  • KEEP: 用于频繁访问的数据,建议设置较小但高命中率。
  • NORMAL: 用于常规访问的数据,适当增大以提高命中率。
  • RECYCLE: 用于不太频繁访问的数据,保持中等大小。

注意一个事项:缓冲池不是真实物理内存占用。

  • 缓冲池是数据库系统用来提高性能的内存区域,存储在物理内存中的数据页。
  • 它是一个逻辑概念,表示数据库如何使用物理内存,而不是物理内存本身。
  • 优化缓冲池的大小和管理策略,可以显著提高数据库的性能和响应速度。

输出:

代码语言:javascript
代码运行次数:0
运行
复制
KEEP	1024	1
RECYCLE	3072	0.9513388117336025
FAST	1024	0.9999996457697699
NORMAL	9216	0.9777671570939879
ROLL	1024	1

查看死锁

代码语言:javascript
代码运行次数:0
运行
复制
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 DS
ON
        DS.TRX_ID = L.TRX_ID
LEFT JOIN V$SESSIONS SS
ON
        SS.TRX_ID = L.TID
WHERE
        L.BLOCKED = 1
LIMIT 100;

杀死 Session

代码语言:javascript
代码运行次数:0
运行
复制
SP_CLOSE_SESSION ( 占用锁的会话 ID );

查询历史死锁

代码语言:javascript
代码运行次数:0
运行
复制
SELECT
    DH.TRX_ID AS "事务ID",
    SH.SESS_ID AS "SESSION_ID",
    WM_CONCAT(TOP_SQL_TEXT) AS "SQL"
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
LIMIT 100;

查看当前活跃的会话消耗的内存

代码语言:javascript
代码运行次数:0
运行
复制
-- 查看当前活跃的会话消耗的内存
SELECT
    	B.CURR_SCH AS "当前模式",
        B.USER_NAME AS "操作账号",
        B.SESS_ID AS "SESSION_ID",
        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
        AND B.STATE = 'ACTIVE'
GROUP BY
        A.CREATOR,
        B.SQL_TEXT
ORDER BY
        TOTAL_M DESC
LIMIT 1000;

统计信息(提升很有效)

统计信息概述

统计信息主要是描述数据库中表和索引的大小数以及数据分布状况等的一类信息。比如:表的行数、块数、平均每行的大小、索引的高度、叶子节点数以及索引字段的行数等。

统计信息对于 CBO(基于代价的优化器)生成执行计划具有直接影响。例如在嵌套循环连接(链接)中需要选择小表作为驱动表,两个关联表哪个是小表完全取决于统计信息中记录的数据量信息。此外,访问一个表是否要走索引,关联查询能否采用其它关联方式等都是 CBO 基于统计信息确定的。因此,统计信息的准确是生成最优执行计划的必要前提。

收集统计信息

DM 收集统计信息的方法分为手动收集和自动收集。

手动收集
代码语言:javascript
代码运行次数:0
运行
复制
--收集指定用户下所有表所有列的统计信息:
DBMS_STATS.GATHER_SCHEMA_STATS('username',100,TRUE,'FOR ALL COLUMNS SIZE AUTO');

--收集指定用户下所有索引的统计信息:
DBMS_STATS.GATHER_SCHEMA_STATS('usename',1.0,TRUE,'FOR ALL INDEXED SIZE AUTO');
--或 收集单个索引统计信息:
DBMS_STATS.GATHER_INDEX_STATS('username','IDX_T2_X');

--收集指定用户下某表统计信息:
DBMS_STATS.GATHER_TABLE_STATS('username','table_name',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');

--收集某表某列的统计信息:
STAT 100 ON table_name(column_name);

注意 统计信息收集过程中将对数据库性能造成一定影响,避免在业务高峰期收集统计信息。 自动收集

DM 数据库支持统计信息的自动收集,当全表数据量变化超过设定阈值后可自动更新统计信息。

代码语言:javascript
代码运行次数:0
运行
复制
--打开表数据量监控开关,参数值为 1 时监控所有表,2 时仅监控配置表
SP_SET_PARA_VALUE(1,'AUTO_STAT_OBJ',2);

--设置 SYSDBA.T 表数据变化率超过 15% 时触发自动更新统计信息
DBMS_STATS.SET_TABLE_PREFS('SYSDBA','T','STALE_PERCENT',15);

--配置自动收集统计信息触发时机
SP_CREATE_AUTO_STAT_TRIGGER(1, 1, 1, 1,'14:36', '2020/3/31',60,1);

/*
函数各参数介绍
SP_CREATE_AUTO_STAT_TRIGGER(
    TYPE                    INT,    --间隔类型,默认为天
    FREQ_INTERVAL         INT,    --间隔频率,默认 1
    FREQ_SUB_INTERVAL    INT,    --间隔频率,与 FREQ_INTERVAL 配合使用
    FREQ_MINUTE_INTERVAL INT,    --间隔分钟,默认为 1440
    STARTTIME              VARCHAR(128), --开始时间,默认为 22:00
    DURING_START_DATE    VARCHAR(128), --重复执行的起始时间,默认 1900/1/1
    MAX_RUN_DURATION    INT,    --允许的最长执行时间(秒),默认不限制
    ENABLE                  INT     --0 关闭,1 启用  --默认为 1
);
*/

查看统计信息

代码语言:javascript
代码运行次数:0
运行
复制
--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。
dbms_stats.table_stats_show('模式名','表名');

--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。 返回两个结果集:一个是索引的统计信息;另一个是直方图的统计信息。
dbms_stats.index_stats_show('模式名','索引名');

--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。
dbms_stats.COLUMN_STATS_SHOW('模式名','表名','列名');

更新统计信息

代码语言:javascript
代码运行次数:0
运行
复制
--更新已有统计信息
DBMS_STATS.UPDATE_ALL_STATS();

删除统计信息

代码语言:javascript
代码运行次数:0
运行
复制
--表DBMS_STATS.DELETE_TABLE_STATS('模式名','表名','分区名',...);

--模式
DBMS_STATS.DELETE_SCHMA_STATS('模式名','','',...);

--索引
DBMS_STATS.DELETE_INDEX_STATS('模式名','索引名','分区表名',...);

--字段
DBMS_STATS.DELETE_COLUMN_STATS('模式名','表名','列名','分区表名',...);

特殊说明:

代码语言:txt
复制
 上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:[www.zanglikun.com](https://www.zanglikun.com/)
代码语言:txt
复制
 第三方平台不会及时更新本文最新内容。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 官方链接参考:
  • 正文
    • 先获取硬件信息
    • 获取达梦基本信息
    • v$licens 优先排查 MAX_CPU_NUM
    • 查看达梦内存分配状态
      • dual 方式一
      • v$sysstat 方式二:
    • 正在执行的SQL
      • 统计不同账号连接的数量
    • 慢SQL排查
    • 查看缓冲池命中率
      • 内存分配
    • 查看死锁
    • 杀死 Session
    • 查询历史死锁
    • 查看当前活跃的会话消耗的内存
    • 统计信息(提升很有效)
      • 统计信息概述
      • 收集统计信息
      • 查看统计信息
      • 更新统计信息
      • 删除统计信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档