针对单条 SQL 执行的性能调优

针对 SQL 执行时间的性能调优是最常见的性能调优,关注的问题是某一条或某一类 SQL 的执行时间或者执行资源的消耗(如内存、磁盘 IO 等)。单条 SQL 的性能调优往往与该 SQL 的执行计划相关,因此,执行计划的分析是该调优场景的最重要的手段。一般来说,应该首先通过静态分析 SQL 的执行计划来找到可能的调优点。

排除优化器自身的 bug 原因,为了使某些 SQL 的执行时间或资源消耗符合预期,一般需要用户对数据库的设置做相应的修改,常见的手段包括:

  • 修改系统配置项或系统变量

  • 对数据 schema 进行修改,包括创建数据分区、创建二级索引等

  • 修改用户 SQL,包括对 SQL 做等价改写、增加 HINT 等

  • 调整并行查询的并行度

一条 SQL 从发送到数据开始执行,到返回结果给用户,会经历队列等待、plan cache 查询、计划优化(如果计划缓存不命中)、计划执行、返回结果等过程。当发现 SQL 的响应时间增加时,第一步应该明确具体是哪部分的耗时增加,此时采用的一般手段包括 SQL Trace、查询 SQL Audit 表、查看慢查询日志等。只有明确了具体耗时在哪里,才能有针对性的进一步分析问题的根源。

针对单条 SQL 的执行计划性能调优又可以分为单表访问和多表访问两种场景。

单表访问场景

对单表访问 SQL 来说,需要重点关注的问题包括:

  • 访问路径是否开启索引扫描

    访问路径的分析是单表查询的最重要的问题之一,对于使用主表扫描的访问路径来说,执行时间一般与需要扫描的数据量(范围)成正比。一般来说,可以使用 EXPLAIN EXTENDED 命令,将表扫描的范围段展示出来。对于有合适索引的查询,使用索引可以大大减小数据的访问量,因此对于使用主表扫描的查询,要分析没有选中索引扫描的原因,例如是由于不存在可用的索引,还是索引扫描范围过大以至于代价过高。

  • 是否存在排序或聚合操作

    排序或聚合往往都是比较耗时的操作。优化器为了尽可能的降低执行时间,在有合适索引可用时,考虑直接使用索引的顺序以避免额外的排序操作,同理,用户也可以根据经常需要排序的列,创建合适的索引,以避免不必要的排序操作。

  • 分区裁剪是否正确

    分区裁剪是分区表优化的重要手段,一般来说,只要用户提供了合适的分区条件,优化器会自动跳过无需访问的分区。

  • 是否需要调整查询的并行度

    提高查询的并行度可以使用更多资源的代价获取单条 SQL 查询的性能提升,当查询牵涉到的数据量较大,分区数目较多时,可以通过提高并行度的方式加快执行时间。

多表访问场景

针对多表访问的 SQL,不仅要关注单表的 SQL 调优的重点问题,还需要关注多表间的连接问题,需要分析的点包括:

  • 连接顺序

  • 连接算法

  • 跨机或并行连接的数据再分布方式

  • 查询改写

针对吞吐量的性能调优

针对吞吐量的性能调优主要是考虑在一定资源(CPU、 IO、 网络等)情况下,能够将数据库系统处理请求量最大化,我们在新业务上线以及各种大促活动前往往需要进行吞吐量评估及吞吐量的性能调优。

吞吐量性能调优可考虑以下几个方面:

  • 优化慢 SQL

    大量慢 SQL 请求会消耗大量的资源,导致整体吞吐量上不去,可按如下步骤处理:

  1. 通过 OCP 的 TOP SQL 功能或利用 plan cache 视图查询耗时为 TOP N 的 SQL。

  2. 找到具体的慢 SQL,可针对单条 SQL 进行性能调优。

  • 均衡 SQL 的请求流量资源

    在多机环境下,我们需要尽量将所有机器资源都能使用到,因此需要考虑流量是否均衡,可以通过 sql_audit 查看 SQL 请求是否均衡,影响均衡的因素主要有:

  • ob_read_consistency 如何设置

  • primary zone 如何设置

  • proxy 或 Java 客户端路由策略相关设置

  • 业务热点查询分区是否均衡

  • 均衡子计划的 RPC 请求流量资源

    大量分布式计划时一般都设置了弱读,资源消耗主要在子计划的 RPC 请求上,在 SQL 请求均衡的情况下,通过 sql_audit 可查看子计划 RPC 请求是否均衡,影响这些子计划请求是否均匀的主要因素有:

  • OBServer 内部路由策略相关设置

  • 业务热点查询的分区是否均衡