Skip to content

SQL调优概述

随着互联网技术在商业应用中的广泛普及,构建与数据库之上的应用日益庞大复杂,随之数据库性能表现的重要性也越发凸显。在数据库的众多性能问题中,SQL性能问题占有极大的比例,因此SQL性能调优是数据库管理员进阶需要掌握的一项重要技能。

1. 关于SQL调优

SQL调优是诊断和优化未能满足性能指标的SQL语句的行为,需要不断的迭代,以满足特定的、可度量的、可实现的目标。

2. SQL调优的目的

当SQL语句无法按照预期性能指标执行时,就会成为一个我们需要解决的性能问题。在确定问题所在后,典型的性能调优至少包含一个以下目标:

  • 减少用户响应时间,这意味着减少用户发出请求到接收请求的时间。
  • 提高吞吐量,这意味着使用最少的资源来处理请求。

考虑这样一个场景,对于一条执行时间为30秒的SQL语句,在硬件资源充足的情况下,考虑减少用户效应时间,我们可以使用并行来提高执行效率;在硬件资源紧张的时候,考虑吞吐量,则需要通过索引、HINT等手段来减少资源的处理请求。问题不同则目标不同,目标不同则使用的手段也会不同。

3. SQL调优步骤

在确定调优目标之后(例如将用户响应时间从60秒降低到5秒),问题就变成了如何实现此目标。SQL调优通常是一个迭代的过程,为了实现得到目标,典型的SQL调优需要不断的重复下述的一个或多个步骤:

3.1 识别高负载语句

通过查看过去的执行历史记录,找到消耗了较多系统资源的SQL语句。

3.2 收集性能相关的数据

优化器统计信息是SQL调优的关键,如果统计信息不存在或不够及时准确,那么优化器将无法生成最优的执行计划。与SQL性能相关的其他数据包括该语句访问的表和视图的结构,以及该语句可用的任何索引的定义,方便后续性能问题原因的分析。

3.3 确定性能问题产生的原因

对于特定的SQL语句,要确定性能问题产生的原因,最重要的手段是分析执行计划。
通常来说,SQL性能问题的原因包括:

  1. 缺少SQL访问结构
    缺少索引、物化视图、分区之类的SQL访问结构是导致SQL性能不佳的典型原因。最佳的访问结构可以将SQL性能提高几个数量级。
  2. 次优的执行计划
    优化器的主要作用是给出最优(较优)的执行计划。有时候因为优化器自身的局限,会选择访问路径不理想的计划。例如,选择率较低的条件在大表上使用全表扫描,而不是索引;多表查询的连接顺序未能让可以过滤更多数据的两表连接最先执行。
  3. 陈旧的优化统计数据
    当统计信息维护操作(自动或手动)无法跟上DML导致的表数据更改时,收集到的统计信息可能会过时。由于表上的陈旧统计信息无法准确反映表数据,因此导致优化器基于错误信息做出决策并生成次优执行计划。
  4. 低效的SQL语句设计
    如果编写SQL语句以使其执行不必要的工作,那么优化器将无法做很多事情来提高其性能。低效设计的例子包括:
    • 忽略添加连接条件,导致笛卡尔积连接
    • 指定UNION而不是UNION ALL
    • 使子查询针对外部查询中的每一行执行
  5. 硬件问题 受限于当前硬件环境(CPU、内存、IO、网络等),所有的优化手段都不足以达到预期性能,则需要做硬件扩展。
  6. 架构问题
    单机硬件扩展无法解决的情况下,则需要考虑读写分离集群等方案。

3.4 定义问题的范围

解决方案的范围必须与问题的范围相匹配。在数据库级别考虑一个问题和在语句级别考虑一个问题的解决方案是不一样的。

3.5 实施优化手段

在步骤3中,我们可以得知SQL性能问题产生的原因较为多样,所以优化手段的实施也会因情况而异。例如,我们可能会通过将UNION改写成UNIONALL来提高性能,也可能通过创建索引来提高性能。

3.6 评估优化效果

在实施优化手段后,通过实际执行来评估优化效果是否达到了预期。

4. SQL调优工具

为了方便用户调优,在这里提供两类SQL调优工具:

  • 诊断技能: 用来诊断SQL性能问题的理论。
  • 优化手段: 用来解决SQL性能问题的优化手段。

4.1 诊断技能

进行SQL性能优化前,需要掌握一些数据库的基础知识。比如:

  1. SQL和PLSQL
  2. 数据库查询优化器基础
  3. 执行计划