作为数据库运维人员,SQL性能优化是一个无法绕过且复杂的话题。它不仅涉及到查询语句的编写技巧,还包括数据库设计、索引规划、执行计划分析等多个层面。sql的优化能力也是运维人员最重要的技能之一,能够快速定位sql语句的性能问题,并且提出恰当的优化方案是一个需要长期锻炼的重要能力。本文将从基础的sql性能优化出发,结合部分过去优化其他类型数据库的经验,做出一些简单的学习总结。
SQL性能问题通常由以下几个方面引起:
dm8本身提供了一系列配置,供运维人员定位慢sql、高代价sql,我个人理解,慢sql、高代价sql、大sql三者并不能简单的等同看待,而应当根据实际情况判断优化的优先级,例如某类定期导数、稽核性质的sql,仅定时的在业务低峰期执行,虽耗时较长,涉及数据量较大,但优化优先级并不高,甚至可以忽略。
通过配置SVR_LOG
参数和sqllog.ini
文件,可以启用SQL日志记录,记录下执行时间超过特定阈值的SQL语句,即是我们常见的慢sql日志,这是最常用且直接的记录问题方法,但也要考虑对慢sql的日志本身是否也会拖累数据库的运行性能,因此达梦也引入了异步日志功能,尽量减少记录日志本身对数据库的消耗。可以通过直接阅读慢sql日志,或调用额外的日志分析工具DMlog(类似于mysql常用的pt-digest-query)进行进一步的分析,定位对当前数据库性能影响较大的待优化语句。
利用系统视图如V$LONG_EXEC_SQLS
,自动记录并分析执行时间超过设定阈值的SQL语句。开启系统视图需要配置动态参数 ENABLE_MONITOR=1、MONITOR_TIME=xxxx,但enable_monitor等于1的情况下,对某些大sql可能会造成性能影响,从我个人的角度出发,我认为使用跟踪日志是更为合适也更为易用的方法。
执行计划是数据库执行SQL语句的具体步骤,分析执行计划是最重要的sql性能定位步骤之一,通过分析执行计划,可以看出sql语句在运行过程中的具体动作,判断具体的性能瓶颈位置,包括是否存在索引规划不合适、统计信息过期等问题。
dm的索引存储结构采用的是b*tree,与mysql使用的b+tree稍有差异,主要体现在b*tree结点使用率要求为2/3,略高于b+tree的一半,但基本优化思路类似,一是需要减少检索的树高度,即减少叶子节点的层数,二是尽量减少回表。
为高频查询字段创建索引。
避免为低选择性的列创建索引,即选择过滤性高的字段。
考虑联合索引以优化多条件查询。
不要过多创建赘余索引,避免占用存储空间。
但在使用过程中,还需要考虑部分索引无法使用的情况:
组合索引中,条件列中没有组合索引的首列。
条件列带有函数或计算。
索引排序是按照字段值进行排序的,字段值通过函数或计算后的值索引无法获取。
索引过滤性能不好时。
定期关注并更新索引统计信息,避免因统计信息过期导致的执行计划变动。
改写SQL语句可以减少资源消耗,提升执行效率。
GROUP BY
通过WHERE子句预先过滤,尽量将更少的结果集放入分组计算中,减少分组计算的代价。
UNION ALL
替换UNION
当合并操作不需要去除重复数据时,使用UNION ALL
替换掉UNION
,
EXISTS
替换IN
在子查询中,使用EXISTS
可以避免不必要的全表扫描。
在程序使用过程中,多使用commit,即在不影响程序逻辑的前提下,尽量将大事务拆分为多个小事务,可以提高程序的运行效率,释放出在运行过程中所持的锁等资源。
在实际工作中,SQL优化是一个需要持续关注和投入的过程。在日常运维过程中,应该培养性能的敏感度,及时发现性能退化。实际的业务运行过程中,数据库仅是其中的一环,当遇到性能问题时,在分析慢SQL的同时,还要考虑分析整个应用的性能瓶颈,从整体链路出发判断性能的瓶颈所在。当然,最重要的一点仍然是需要不断的学习和实践,积累丰富的经验,才能更高效的定位和处理问题。
文章
阅读量
获赞