SQL数据库慢查询优化详解!数据库参数和SQL语句优化分析说明

658 阅读5分钟

这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

数据库优化

  • 数据库优化要保证以下三点:
    • 日志不能小
    • 缓存足够大
    • 连接足够用
  • 数据库事务提交后需要将事务对数据的修改刷新到磁盘上,这样才能保证数据的持久性.这个刷新过程是一个随机写的过程,性能低.如果每次事务提交都需要对磁盘进行刷新,会极大影响数据库的性能
  • 可以在数据库架构设计中使用以下方式进行优化:
    • 先将事务写到日志文件RedoLog, 将随机写优化成顺序写
    • 添加一层缓存结构Buffer, 将每次写优化成批量写

目标

  • 根据不同的角色,数据库优化包含以下几个目标:
    • 业务角度: 减少客户端页面响应时间
    • 数据库角度: 减少数据库SQL响应时间
    • 数据库服务器角度:
      • 充分使用数据库服务器物理资源
      • 减少数据库服务器CPU的使用率
      • 减少数据库服务器IO使用率
      • 减少数据库服务器内存使用率

指标

  • 减少SQL的平均响应时间
  • 减少数据库服务器CPU的使用率
  • 减少数据库服务器的IO使用率

流程

  • 了解优化问题: 首先要尽可能了解优化的问题
  • 收集系统信息: 收集问题期间系统信息并做好存档
  • 制定优化目标: 根据当前系统问题表现制定优化目标并和客户沟通目标达成一致
  • 分析性能问题: 通过一系列工具分析系统问题
  • 制定优化方案
  • 实施优化方案

数据库参数优化

  • 数据库架构都包括以下几个方面,可以调整以下方面参数使得数据库达到最佳性能:
    • 数据缓存
    • SQL解析区
    • 排序内存
    • REDO以及NUDO
    • , LATCH, MUTEX
    • 监听及连接
    • 文件读写性能

Oracle

参数类别参数名参数值说明
数据缓存SGA_TAGET
MEMORY_TARGET
DB_CACHE_SIZE
物理内存的70% - 80%越大越好
SQL解析SHARED_POOL_SIZE4GB - 16GB不宜设置过大6GB
监听连接PROCESS
SESSIONS
OPEN_CURSORS
根据业务需求设置一般为业务预估连接数的120%
其余参数SESSION_CACHED_CURSORS大于200解析

MySQL

  • 对于MySQLInnoDB引擎有如下参数设置:
参数类别参数名参数值说明
数据缓存INNODB_BUFFER_POOL_SIZE物理内存的50% - 80%越大越好
日志记录Innodb_log_buffer_size
sync_binlog
16MB - 32MB
1, 100, 0
根据运行状况调整
1时安全性最好
监听连接max_connections根据业务需求设置可以预留一部分值
文件读写性能innodb_flush_log_at_trx_commit2安全和性能的折中考虑
其余参数wait_timeout
interactive_timeout
28800避免应用连接中断

SQL优化

定位慢查询SQL

  • 定位慢查询SQL可以通过两个表象进行判断
    • 系统级表象:
      • CPU消耗严重
      • IO等待严重
      • 页面响应时间过长
      • 项目日志出现超时等错误
        • 使用sar命令和top命令查看当前系统的状态
        • 也可以使用PrometheusGrafana监控工具查看当前系统状态
    • SQL语句表象:
      • SQL语句冗长
      • SQL语句执行时间过长
      • SQL从全表扫描中获取数据
      • 执行计划中的rowscost很大
  • 根据不同的数据库使用不同的方式获取问题SQL
    • MySQL:
      • 慢查询日志
      • 测试工具loadrunner
      • ptquery工具
    • Oracle:
      • AWR报告
      • 测试工具loadrunner
      • 相关内部视图v,, session_wait
      • GRID CONTROL监控工具

SQL语句优化

  • 合理使用索引:
    • 索引少了查询慢. 索引多了占用空间大,执行增删改语句需要动态维护索引,影响性能
    • 选择率高,重复值少并且where中频繁引用的字段需要建立B树索引
  • 使用UNION ALL替代UNION
  • 禁止使用SELECT * 的写法
  • 对join的字段建立索引
  • 避免复杂的SQL语句,可以转换成多个子查询,在业务层处理
  • 使用explain sql查看SQL的执行计划:
字段说明
id每一个被执行的操作标识,标识对象被操作的顺序
ID的值较大的先被执行.如果相同,执行顺序从上向下
select_type查询中每个select语句的类型
table被操作的对象的名称,通常是表名.也会包含其余格式
partitions匹配的分区的信息,对于非分区的表值为NULL
type连接操作的类型
possible_keys可能用到的索引
key优化器实际使用的索引
最好到最差的索引依次为const, eq_reg, ref, range, index, ALL
对于ALL类型的索引一定要进行优化
key_len优化器选定的索引键长度,以字节为单位
ref表示本行对象被操作对象的参照对象, 对于无参照对象时为NULL
rows执行查询所扫描的元组个数
filtered条件表上数据被过滤的元组个数百分比
extra计划执行的重要补充信息
当出现Using filesort, Using temporary时要对SQL语句进行优化

总结

  • 使用explain查看SQL语句的执行计划
  • 如果有告警信息,查看告警信息的show warnings
  • 查看SQL语句涉及的表结构和索引信息
  • 根据执行计划对SQL语句需要优化的地方进行优化
  • 根据需要优化的情况执行表结构的修改,索引的添加 ,SQL语句的改写等操作
  • 再次使用explain查看优化后的执行时间和执行计划
  • 根据优化效果选择继续优化,还是优化成功