一、DM7查询优化基本思路
遇到数据库性能问题,一般从下面3个方面分析
1、操作系统性能诊断:
LINUX常用性能监控命令
- 使用top命令查看cpu使用率
- 使用iostat命令查看磁盘I/O使用情况
- 使用dstat工具查看磁盘I/O使用情况
- 使用free命令查看内存使用情况
- 使用nmon工具监控系统一段时间的整体情况
- 使用perf top命令查看系统热点情况
这些都是运维方面一些比较基础的操作,网上有大量相关的资料,这里就不再赘述了。
分析:如果发现数据库主机的cpu、I/O、内存等使用率很高,往往说明数据库存在性能瓶颈。也可能是硬件本身存在问题,但这种可能性比较小,也容易排除。
2、数据库架构优化
数据库架构是否最优?
根据业务的特性,选择合适的数据库架构非常必要。
数据库参数优化:
3、SQL分析优化
数据库会话监控:
SQL优化:
数据库的性能问题最终都要涉及到SQL优化,处理流程:
生成SQL日志
SQL日志分析流程:
PS:对于比较大SQL日志(大于10G),建议采用ETL入库,入库较快。
SQL汇总分析
确定目标SQL
如XX项目,入库生产SQL日志,汇总分析,最终找出待优化的3类目标SQL,如下图。接着就去做具体的SQL优化了。
SQL优化思路
高并发SQL优化案例
XX项目刚上线,并发很大,IO、CPU都很高,数据库经常瘫痪。分析SQL日志,找出几条执行次数最多的SQL,如下图:
分析及优化:
效果:优化后系统比较稳定,IO、CPU降到原来的1/3,瘫痪次数大大减少。
SQL性能分析工具-ET
ET是DM7自带的分析工具,能统计SQL每个操作符的时间花费,从而定位到有性能问题的操作,指导用户去优化。
INI参数ENABLE_MONITOR=3时,ET才能使用。
阻塞与死锁
阻塞和死锁是拖慢系统性能的两大元凶。
二者有些差异:
- 死锁是相互堵塞;而阻塞是单向的
- 数据库自动识别死锁并解锁;而阻塞不能
- SQL日志中会记录死锁信息;而阻塞没有,需要人工分析
下图中记录了一条死锁信息:
阻塞产生的原因及解决思路:
- 相同数据的并发操作是主因,业务上尽量避免热点数据的批量操作,比如多个审核员同时从作业池中随机取10张单子,就很可能取到重复,造成阻塞。
- 慢SQL会使阻塞恶化,加大了阻塞的时间,应尽量优化SQL。
阻塞分析过程:
1、监控阻塞会话,同时保证sql日志已经打开
2、监控到阻塞信息,并保留数据,供后面分析使用。
可以看出事务[316624]被事务[316646]所阻塞,后面可以从sql日志中找到完整事务给应用分析。
3、将SQL日志入库,表名为log_commit,表结构如下:
4、找出阻塞的两个事务,然后优化慢sql,同时反馈给应用去优化业务
|
--等待的事务 select trx_id,starttime,sqlstr,exetime from log_commit where trx_id='316624'; --阻塞的源头事务 select trx_id,starttime,sqlstr,exetime from log_commit where trx_id='316646'; |
二、DM7执行计划
什么是执行计划?
- 一条SQL语句在DM数据库中执行过程或访问路径的描述
如何查看执行计划?
|
--通过EXPLAIN命令查看 EXPLAIN SELECT * FROM SYSOBJECTS; 1 #NSET2: [0, 1711, 396] 2 #PRJT2: [0, 1711, 396]; exp_num(17), is_atom(FALSE) 3 #CSCN2: [0, 1711, 396]; SYSINDEXSYSOBJECTS(SYSOBJECTS as SYSOBJECTS) |
执行计划包含哪些重要信息?
- 一个执行计划由若干个计划节点组成,如上图中的1、2、3
- 每个计划节点中包含操作符(CSCN2)和它的代价([0, 1711, 396])等信息
- 代价由一个三元组组成[代价,记录行数,字节数]
- 代价的单位是毫秒,记录行数表示该计划节点输出的行数,字节数表示该计划节点输出的字节数
-解读一下第三个计划节点:操作符是CSCN2即全表扫描,代价估算是0ms,扫描的记录行数是1711行,输出字节数是396个
具体的操作符解读就不在此细述了。
三、DM7统计信息与索引详解
什么是统计信息?
统计信息主要是描述数据库中表,索引的大小,规模,数据分布状况等的一类信息。比如,表的行数,块数,平均每行的大小,索引的高度、叶子节点数,索引字段的行数,不同值的大小等,都属于统计信息。
两种统计方式:
- 频率直方图:适用于取值范围比较少的列,例如有些字段的取值范围非常有限,比如人类的年龄,一般不可能超过120, 因此无论表中有多少记录,年龄字段的唯一值个数都不会超过120, 我们可以采样部分记录,统计出每个年龄(0-120)的记录数,可以使用120个(V, count)二元组作为元素的数组,来表示这个频率直方图。
- 等高直方图:频率直方图虽然精确,但是它只能处理取值 范围较小的情况,如果字段的取值范围很大,那么就不可能为每一个值统计出它的出现次数,这个时候我们需要等高直方图。等高直方图是针对一个数据集合不同值 个数很多的情况,把数据集合划分为若干个记录数相同或相近的不同区间,并记录区间的不同值个数。每个区间的记录数比较接近,这就是所谓等高的含义。
统计信息对CBO影响非常重大,因此我们要及时更新统计信息。但是统计信息由于某些原因总存在一些缺陷, CBO也很难百分百估算正确。为更好理解CBO估算方式,我们必须要了解以下情形:
1、对于等高直方图,CBO会认为每个区间中的数据都是近似均匀分布的,实际上数据可能分布非常崎岖。
2、等高直方图区间越多,统计越精确,而实际上数量有限,最大为1000。
3、对于组合索引的多个列,统计信息只有每个列的独立分布情况,而无法知道列之间的关联分布。
索引存储结构
了解索引的存储结构对于正确使用和优化索引有很大帮助。
最常见的索引结构为B*tree索引,下图是一个B*树索引存储结构图。
在什么情况下使用B*树索引?
-
仅当要通过索引访问表中很少的一部分行(1%~20%)
- 索引用于访问表中的行(只占一个很小的百分比)
-
如果要处理表中的多行,而且可以使用索引而不用表
- 索引用于回答一个查询:索引提供了足够的信息来回答整个查询,不需要去访问表
- 索引可以作为一个“较瘦”版本的表
索引对DML语句的影响
天下没有免费的午餐,索引能提高查询性能,也能拖慢DML的效率。
下面在单机做了一个测试,在一个千万行的表上分别添加0~10个索引,记录更新一万行记录的时间,如下表:
|
序号 |
索引数量 |
DML时间 |
增加两个索引耗时 |
|
1 |
0 |
122ms |
|
|
2 |
2 |
9.5s |
19s |
|
3 |
4 |
30.8s |
20s |
|
4 |
6 |
1分12s |
24.6s |
|
5 |
8 |
1分31s |
19.7s |
|
6 |
10 |
1分40s |
20s |
上面具体的数字没有意义,因为不同的硬件环境和参数,数据会不一样。但是通过比较能发现,索引越多,表上DML操作的速度越慢。所以使用索引一定要注意质量,可有可无的索引必须要删掉。另外,大批量更新数据时,允许的话可以先删除索引,更新完毕后再重建,这样效率会高一些。
在日常的运维过程中,我们一般“SQL日志+DEM工具+manager”搭配使用,能找到一些执行效率差的SQL语句,并通过分析给出优化建议。但是个人感觉达梦数据库性能优化部分还有一些可以改进的地方,比如:
1、一些优化相关的动态视图存储的信息有限,设定了记录数的上限,如:
V$SQL_STAT_HISTORY,这个动态视图记录历史SQL语句执行的资源开销,单机最大行数为10000。事实上这部分记录的信息非常有限。
建议根据数据库内存的容量,灵活调整这块区域的大小。
2、SQL日志的功能:做sql日志解析时,需要将本地文件系统上的数据通过jar包转换,生成excel,而且excel需要windows机器打开(linux日常运维无法直连,所以无法调xwindow),整个分析过程比较长。excel列表中的数据,没有时间的维度,无法分析具体某个时间点或小的时间段内有哪些慢SQL。
建议参考oracle数据库v$active_session_hisotry\dba_hist_active_sess_history的设计方法将这部分信息记录到数据库表中去。
3、没有系统自动收集统计信息的功能,因此数据库统计信息收集功能是关闭的,造成很多数据库对象没有统计信息。
建议给数据库增加自动收集统计信息的功能,配置默认策略,并默认为开启状态。
4、DEM的采集粒度太大,目前最小的粒度是1次/分钟,对于执行时间<1分钟的sql,很可能无法采集到相关信息。显然,对数据库分析优化来说这种采集粒度是远远不够。
建议参照建议2,将会话快照的功能放在数据库本地,并对于ASH\AWR设置不同的采样粒度。