DMDSC达梦共享存储集群在压测过程中会出现单条SQL执行很快,当并发较高的情况下会出现系统卡慢,操作系统SYS进程消耗大量CPU资源,SYS进程占CPU资源较高,导致系统卡顿。通过perf top 命令查看(如下图)发现系统进程spinlock进程占比较高,当并发数据达到500并发时,服务器CPU资源所有核数全部被100%占用,系统表现得较为卡顿。
一般情况下,遇到这种带kernel字样的内核进程占cpu资源较高的场景,都需要关注操作系统优化参数是否有问题,经过咨询操作系统厂商专家表示操作系统参数设置没有问题,至此我在百度上根据关键字搜索了一下相关的文章,在墨天轮的一篇技术文章《高并发数据库中的spinlock优化》介绍,调整达梦数据库的SPIN_TIME参数可以解决类似问题,经过核查发现,目前数据库中的SPIN_TIME参数已经是最大值4000,没有调整空间。
接下来的优化思路还是回归到应用系统本身,通过开启sql日志把压测过程中所有发到数据库服务器端的sql语句、包括每个sql语句执行时间、执行频次等都记录下来。通过分析完整的sql日志发现,这些sql语句单条执行都较快,但当并发数达到一定级别的时候就会出现执行需要花费较长时间的情况。对执行时间较长的sql拿出来具体分析,通过分析每条sql的执行计划发现,这些sql语句的执行计划里面存在大量BLKUP2二次回表操作符和索引没有建到位的情况,经过咨询公司领导和专家并获得相关指导,把所有SQL语句的BLKUP2二次回表操作符消除掉,把相关sql语句的索引建到位,同时在调整了数据库端部分参数的情况下,sys进程spinlock进程占比高的问题被彻底消除掉。经过重新压测,当系统并发达到8000时系统性能依然保持良好,经过长时间的观察发现在压测期间cpu总体占比不会超过30%。符合用户预期,已经彻底消除spinlock占比较高的问题。
下面分两个部分介绍sql优化过程和数据库参数调整过程:
一、消除BLKUP2回表操作符、并相关SQL语句所涉及的索引建到位。
--构造数据
create table TB_EMPLOYEE AS select * from DMHR.EMPLOYEE;
--构造查询语句
select
EMPLOYEE_ID ,
EMPLOYEE_NAME,
EMAIL ,
PHONE_NUM ,
HIRE_DATE ,
SALARY
from
TB_EMPLOYEE
where
EMPLOYEE_ID in (1001, 1002, 4004)
and DEPARTMENT_ID IN (101,102,404);
没有任何索引的执行计划
由执行计划可以看出,存在全表扫描,在高并发的场景下,全表扫描是非常影响性能的。所以我们就需要通过来新建索引的方式消除全表扫描。那如何把索引建到位,这个需要花费一番功夫来进行优化,下面我们就分别展示新建不通类型的索引,同一条SQL语句执行计划的变化情况。
--新建索引1
create index INDEX_TB_EMPLOYEE_001 ON TB_EMPLOYEE(EMPLOYEE_ID);
当新建索引1时,执行计划按照预期走了索引1,但是where后面的条件只有EMPLOYEE_ID条件走了索引定位,而另外一个条件DEPARTMENT_ID并没有走索引,如果DEPARTMENT_ID过滤性较好,但过滤性较好的条件并没有走索引,说明我们的索引建得不到位或者不理想,下面我们重新调整索引字段和索引语句。
--新建索引2
create index INDEX_TB_EMPLOYEE_002 ON TB_EMPLOYEE(EMPLOYEE_ID,DEPARTMENT_ID);
新建索引2后,在重新观察执行计划,通过执行计划可以看出,条件EMPLOYEE_ID和条件DEPARTMENT_ID都走了索引定位,从执行计划可以看出索引2明显优于索引1,特别是在高并发的场景下,需要把索引建到位,建到恰到好处,针对一般情况来说到索引2这个层面已经基本满足要求了,但在有些场景下,需要把BLKUP2二次回表的操作符也消除掉,该如何消除这个操作符呢,我们新建索引3,把sql语句所涉及到的相关字段都覆盖到索引3里面。
--新建索引3
create index INDEX_TB_EMPLOYEE_003 ON TB_EMPLOYEE(EMPLOYEE_ID,DEPARTMENT_ID,EMPLOYEE_NAME,EMAIL,PHONE_NUM,HIRE_DATE,SALARY);
新建索引3后,通过执行计划可以看到已经消除了BLKUP2二次回表的操作符,同时在第一次索引定位中where后面的两个条件在第一时间也全部都使用上了。索引3明显要好于索引1和索引2。当然如果select后面涉及到的字段比较多,我们就无法全部覆盖到时,我们至少要达到索引2的层面才行。
二、DMDSC在高并发场景下的部分参数调整。
当然除了做好SQL的优化之外,在高并发的场景下,还需要对部分数据库相关的参数进行调整。在进行参数调整之前,我们先查阅《DM8系统管理员手册》看一下每个参数的具体定义。
- MEMORY_POOL:共享内存池大小,以M为单位。共享内存池是由DM管理的内存。有效值范围:32位平台为(64~2000),64位平台为(64~67108864)。
- ENABLE_FREQROOTS:指定FAST_POOL的管理方式。0:经典模式,系统启动时装入常用的描述页、索引的根、索引的控制页、指定常驻内存的表以及索引第二层的节点,之后不再变化;1:动态模式A,系统启动时装入常用的描述页、索引的根、指定常驻内存的表, 后续按负载情况动态装入频繁访问的页;2:动态模式B, 预装入的页同经典模式,后续按负载情况动态装入频繁访问的页; 3:最大模式,试图把数据页全部装入FAST POOL,如果还有富余,则剩下的空闲FAST POOL空间按各文件实际使用长度按比例预分配,后续不再变化,适合库较小、内存空间大的场景对于ROLL表空间,最多分配0号文件的前FAST_ROLL_PAGES,其中0、1、2模式下优先分配,3模式下按表空间ID和文件ID依次分配。
- SESS_POOL_SIZE:会话缓冲区大小,以 KB 为单位,有效值范围 (16~1024*1024)。若所申请的内存超过实际能申请的大小,则系统将按 16KB 大小重新申请。
- VM_POOL_SIZE:系统执行时虚拟机内存池大小,在执行过程中用到的内存大部分是从这里申请的,它的空间是从操作系统中直接申请的,有效值范围(32~1024*1024)。
- VM_POOL_TARGET:虚拟机内存池能扩充到的最大大小,以 KB 为单位,有效值范围(0~10*1024*1024),0 表示不限制。
以下是这5个参数调整后的值:
参数名称 | 原值 | 调整后的值 |
MEMORY_POOL | 2000 | 10000 |
ENABLE_FREQROOTS | 0 | 1 |
SESS_POOL_SIZE | 64 | 10000 |
VM_POOL_SIZE | 64 | 20000 |
VM_POOL_TARGET | 16384 | 40000 |
具体参数值的调整,除了根据实际场景服务器的配置之外,还需要有丰富的经验来指导调整,在自己没有足够把握的情况下,最好咨询领导和专家,在专家的指导下进行相关参数的调整,当然调整后需要进行持续的跟踪观察测试。
更多资讯请上达梦技术社区了解: https://eco.dameng.com