# 性能诊断调优概述

客户端 SQL执行过程会分为下面几步：

+ 客户端将 SQL 发往 OBPROXY 节点。
+ OBPROXY 将 SQL 发往后端 OBSERVER 节点。
+ OBSERVER 解析 SQL，执行SQL，返回结果给 OBPROXY 节点。
+ OBPROXY 将数据返回给客户端。

OceanBase 的 SQL 性能诊断就是围绕这个链路上几个关键环节进行。如 OBPROXY 的 路由、OBSERVER 的 SQL引擎等。

## SQL 引擎简介

OBSERVER 进程包含 SQL 引擎、事务引擎和存储引擎。其中 SQL 引擎的设计跟 ORACLE SQL引擎设计理念一致。都有 SQL 语法解析、执行计划缓存、软解析、大纲等技术。
OBPROXY 进程并不包含 SQL 引擎，只能做很简单的 SQL 分析，判断 SQL 该路由到后端那个 OBSERVER 节点。未来 OBPROXY 可能会把 OBSERVER 的 SQL 引擎能力也包含进去。

### SQL 执行计划简介

SQL 执行计划简单来说就是 SQL 执行的路径或者算法，影响 SQL 的执行性能。差之毫厘，谬以千里。

OceanBase SQL 引擎支持SQL解析，解析后的执行计划会缓存，下次就可以复用。跟传统数据库一样，SQL 文本不一样，执行计划不会复用。此外，如果SQL文本一样，但是执行环境不一样，执行计划也不会复用。目前所知的执行环境包括运行节点IP、会话级别的并行参数。当然可能还有其他的。所有数据库的SQL执行引擎的成熟度可以从这个小点入手判断。

OceanBase 缓存执行计划的两个视图是：`gv$plan_cache_plan_stat` 和 `gv$plan_cache_plan_explain` 。这是实际运行使用的执行计划，是更准确的。不过初学的时候看这个比较麻烦。所以本文后面先探讨用 EXPLAIN 命令解析的执行计划。

先介绍一些执行计划的大的特点。

+ 没有绝对完美正确的执行计划，尤其是 SQL 比较复杂的时候。
+ 同样的SQL，不同 OBSERVER 版本可能会有执行计划的变化。
+ 同样的SQL，执行计划也不一定一尘不变。影响执行计划变化的因素可能有数据量（或者统计信息）、会话参数（或变量）、数据分布特点、SQL被路由到的节点等。后两者是 OceanBase 特有的。
+ EXPLAIN 解析的执行计划可能跟实际运行的执行计划不一样，受 OBPROXY 和 OBSERVER 的 LOCATION CACHE 和 SQL 路由策略影响。
+ SQL 执行计划可以通过 SQL 注释干预，这个需要改 SQL。如果 SQL 不可以改，可以通过大纲（OUTLINE）在线干预。干预的结果可能成功也可能失败。 这点以后也详细介绍。

### SQL HINTS

OceanBase 支持在 SQL 里使用 HTINTS 来改变执行计划或控制其他行为。

+ 语句级别的hint

```sql
FROZEN_VERSION
QUERY_TIMEOUT
READ_CONSISTENCY
LOG_LEVEL
QB_NAME
ACTIVATE_BURIED_POINT
TRACE_LOG
MAX_CONCURRENT
```

**说明：**

+ `/*+ QUERY_TIMEOUT(100000000) */`：是对SQL 超时时间进行控制。
+ `/*+ READ_CONSISTENCY(weak) */`：是用来设置弱一致性读。
+ `/*+ MAX_CONCURRENT(8) */`: 是用来对 SQL 的并发进行限制的。

+ 计划相关的hint

```sql
FULL
INDEX
LEADING
USE_MERGE
USE_HASH
USE_NL
ORDERED
NO_REWRITE
```

**说明：**

+ `/*+ FULL(表名) */`：是强制对表进行全表扫描。
+ `/*+  LEADING(表名) */`：是强制某表为驱动表。可以间接改变连接算法。
+ `/*+ USE_NL(表a, 表b, 表c） */`：设置表 a b c 的连接算法为嵌套循环。
+ `/*+ ORDERED */`：按照 `from` 子句后的表顺序进行表链接。

## OceanBase 性能诊断思路

OceanBase 性能问题通常包括:

+ 大表查询性能，大批量数据导出性能等。
+ 大事务性能，大批量数据加载性能等。
+ 普通的读写性能。

有些性能问题往往是集群出现稳定性问题之后出现的。比如说网络延时增大或者节点时间误差增大导致的节点状态不稳定，进而影响了性能。磁盘故障或者磁盘空间满导致的合并异常问题，也可能间接影响性能。由于 OceanBase 可靠性很高，即使集群不稳定，也不会出现不可用的状态，所以，稳定性问题隐藏的有点深，不为业务所见。业务更多的时候感知的是性能问题。
当然，运维使用一些监控手段，也是能够及时发现稳定性问题。

下面性能诊断就不考虑稳定性问题带来的性能问题。

性能诊断的方向有下面几个：

+ OBPROXY 节点的负载。包括 CPU、网络、内存等。
+ OBSERVER 节点的负载。包括 CPU、磁盘、内存、网络等。
+ SQL 的执行类型分布（本地 SQL 和远程 SQL 的比例）。
+ SQL 的执行计划。
+ 集群和租户的内存管理（内存参数、转储和合并进度等）。
+ 业务事务的具体 SQL 逻辑。
