
# SQL自诊断
用户在执行INSERT/UPDATE/DELETE/SELECT/MERGE INTO或者CREATE TABLE AS语句时，可能会遇到性能问题。产品内置集成了性能自动诊断功能，并把相关的诊断信息保存到[实时TopSQL](https://support.huaweicloud.com/devg-dws/dws_04_0397.html)中，当配置参数[enable_resource_track](https://support.huaweicloud.com/devg-dws/dws_04_0922.html#ZH-CN_TOPIC_0000001811490709__s9530ecdd2b0d4a98b67b66e32bf8e5d0)为on的时候，这些诊断信息会转存到[历史TopSQL](https://support.huaweicloud.com/devg-dws/dws_04_0398.html)中。通过查询[GS_WLM_SESSION_STATISTICS](https://support.huaweicloud.com/devg-dws/dws_04_0706.html)，[GS_WLM_SESSION_HISTORY](https://support.huaweicloud.com/devg-dws/dws_04_0705.html)，[GS_WLM_SESSION_INFO](https://support.huaweicloud.com/devg-dws/dws_04_0704.html)视图的warning字段可以获得对应的性能诊断信息，为性能调优提供参考。
- SQL自诊断的告警类型与[resource_track_level](https://support.huaweicloud.com/devg-dws/dws_04_0922.html#ZH-CN_TOPIC_0000001811490709__section153571329142612)的设置相关。
  当"resource_track_level"设置为query时，可以诊断多列/单列统计信息未收集、分区未剪枝告警和SQL不下推的告警等非执行态的诊断信息；"resource_track_level"设置为perf或operator时，可以诊断所有的告警场景。
  
- SQL自诊断的诊断范围与[resource_track_cost](https://support.huaweicloud.com/devg-dws/dws_04_0922.html#ZH-CN_TOPIC_0000001811490709__section1089022732713)的设置相关。
  当SQL的代价大于"resource_track_cost"时，SQL才会被诊断。SQL的代价可以通过explain来确认。
  
- 执行EXPLAIN PERFORMANCE或者EXPLAIN VERBOSE的时候，除缺乏多列统计信息之外的SQL自诊断信息也会输出，具体请参考[SQL执行计划](https://support.huaweicloud.com/devg-dws/dws_04_0432.html)。
#### SQL执行性能相关告警场景
目前支持对以下10种导致性能问题的场景上报告警。
1. 多列/单列统计信息未收集。 如果存在单列或者多列统计信息未收集，则上报相关告警。对于这种告警，建议的优化方案是对相关表进行ANALYZE，可参考[更新统计信息](https://support.huaweicloud.com/devg-dws/dws_04_0436.html)和[统计信息调优](https://support.huaweicloud.com/devg-dws/dws_04_0449.html#ZH-CN_TOPIC_0000002052655458)。
   需要特别注意的是，如果查询语句中的OBS外表和HDFS外表未收集统计信息，也会上报统计信息未收集的告警，因为OBS外表和HDFS外表的ANALYZE性能比较差，一般不建议对其进行ANALYZE，但是建议使用ALTER FOREIGN TABLE的语法修改外表的totalrows属性，从而修正外表的行数估算。
   告警信息示例：
   整表的统计信息未收集：
   ```
   Statistic Not Collect
           schema_test.t1
   ```
   单列统计信息未收集：
   ```
   Statistic Not Collect
           schema_test.t2(c1)
   ```
   多列统计信息未收集：
   ```
   Statistic Not Collect
           schema_test.t3((c1,c2))
   ```
   单列和多列统计信息未收集：
   ```
   Statistic Not Collect
           schema_test.t4(c1)
           schema_test.t5((c1,c2))
   ```
   
2. 分区不剪枝。 分区表查询时，常会期望通过分区键上的约束条件进行分区剪枝，从而提升分区表查询性能，但有时候会因为约束条件书写不当，导致分区表没有剪枝，出现查询性能问题，具体请参见[案例：改写SQL排除剪枝干扰](https://support.huaweicloud.com/devg-dws/dws_04_0488.html#ZH-CN_TOPIC_0000002052655502)。
   
3. SQL不下推。 对于不下推的SQL，尽可能详细上报导致不下推的原因。调优方法可参考案例[语句下推调优](https://support.huaweicloud.com/devg-dws/dws_04_0447.html)。
   导致不下推的因素主要有以下两点：
   - 函数导致的不下推 诊断信息中会给出具体的函数名称。函数下推是由函数的shippable属性决定，具体可参见《数据仓库服务SQL语法参考》中"CREATE FUNCTION"语法。
     
   
   - 语法导致的不下推 诊断信息中会提示导致不下推的具体语法，例如：含有With Recursive，Distinct On，row表达式，返回值为record类型的，会告警相应语法不支持下推等等。
     
    
   告警信息示例：
   ```
   SQL is not plan-shipping 
           "enable_stream_operator" is off
   SQL is not plan-shipping 
           "Distinct On" can not be shipped
   SQL is not plan-shipping
           "v_test_unshipping_log" is VIEW that will be treated as Record type can't be shipped
   ```
   
4. 不支持向量化计划 对于不能生成向量化计划的SQL，尽可能详细地上报不支持向量化的原因。
   常见的不支持向量化的因素主要有：
   - 目标列含有返回类型是集合类型的函数。
   
   - 目标列或查询条件、Stream算子的分布键、Limit和Offset子句含有不可向量化的表达式（地理空间类型、数组表达式、Row表达式、XML表达式、参数或返回值有refcursor类型的函数等）。
   
   - Group By子句含有数组等值判断表达式。
   
   - GC_FDW和LOG_FDW不支持向量化。
   
   - 计划含有Cte Scan、Recursive Union、Merge Append、Lock Rows等算子。
   
   
   告警信息示例：
   ```
   SQL is un-vectorized
            Function regexp_split_to_table that returns set is un-vectorized
   SQL is un-vectorized
            Array expression is un-vectorized
   SQL is un-vectorized
            Function array_agg is un-vectorized
   SQL is un-vectorized
            RecursiveUnion is un-vectorized
   ```
   
5. HashJoin中大表做内表。 如果在表连接过程中使用了Hashjoin（可通过[GS_WLM_SESSION_HISTORY](https://support.huaweicloud.com/devg-dws/dws_04_0705.html)的"query_plan"字段查看），且连接的内表行数是外表行数的10倍或以上；同时内表在每个DN上的平均行数大于10万行，且发生了下盘，则上报相关告警。针对这种场景，需要调整HashJoin内外表顺序，具体调优方法参考[Join顺序的Hint](https://support.huaweicloud.com/devg-dws/dws_04_0456.html)。
   告警信息示例：
   ```
   Execute diagnostic information
           PlanNode[7] Large Table is INNER in HashJoin “Vector Hash Aggregate”
   ```
   其中，7为"query_plan"字段文本中编号为7的算子。
   
6. 大表等值连接使用Nestloop 如果在表连接过程中使用了nestloop（可通过[GS_WLM_SESSION_HISTORY](https://support.huaweicloud.com/devg-dws/dws_04_0705.html)的query_plan字段查看），并且两个表中较大表的行数平均每个DN上的行数大于10万行、表的连接中存在等值连接，则上报相关告警。针对这种场景，需要调整表关联方式，禁止当前内外表之间使用NestLoop的关联方式，具体调优方法参考[Join方式的Hint](https://support.huaweicloud.com/devg-dws/dws_04_0457.html)。
   告警信息示例：
   ```
   Execute diagnostic information
           PlanNode[5] Large Table with Equal-Condition use Nestloop"Nested Loop"
   ```
   
7. 大表Broadcast 如果在Broadcast算子中，平均每DN的行数大于10万行，则告警大表Broadcast。针对这种场景，需要禁止Broadcast下层算子做Broadcast动作，具体调优方法参考[Stream方式的Hint](https://support.huaweicloud.com/devg-dws/dws_04_0459.html)。
   告警信息示例：
   ```
   Execute diagnostic information
           PlanNode[5] Large Table in Broadcast "Streaming(type: BROADCAST dop: 1/2)"
   ```
   
8. 数据倾斜 某表在各DN上的分布，存在某DN上的行数是另一DN上行数的10倍或以上，且有DN中的行数大于10万行，则上报相关告警。该告警一般分为存储层倾斜和计算层倾斜，具体调优方法参考[数据倾斜调优](https://support.huaweicloud.com/devg-dws/dws_04_0451.html#ZH-CN_TOPIC_0000002088734289)。
   告警信息示例：
   ```
   Execute diagnostic information
          PlanNode[6] DataSkew:"Seq Scan", min_dn_tuples:0, max_dn_tuples:524288
   ```
   
9. 索引不合理 在基表扫描时，满足下述条件则上报相关告警：
   - 对于行存表：
     - 使用索引扫描，输出行数/扫描行数\>1/1000且输出行数\>1万行。
     
     - 使用顺序扫描，输出行数/扫描行数\<1/1000且输出行数\<=1万行、扫描行数\>1万行。
      
   
   - 对于列存表：
     - 使用索引扫描，输出行数/扫描行数\>1/10000且输出行数\>100。
     
     - 使用顺序扫描，输出行数/扫描行数\<1/10000且输出行数\<=100、扫描行数\>1万行。
      
   
   
   调优方法可参考[算子级调优](https://support.huaweicloud.com/devg-dws/dws_04_0450.html#ZH-CN_TOPIC_0000002052813810)，也可参考案例[案例：建立合适的索引](https://support.huaweicloud.com/devg-dws/dws_04_0476.html#ZH-CN_TOPIC_0000002052655490)和[案例：使用partial cluster key](https://support.huaweicloud.com/devg-dws/dws_04_0490.html#ZH-CN_TOPIC_0000002088734329)。
   告警信息示例：
   ```
   Execute diagnostic information
           PlanNode[4] Indexscan is not properly used:"Index Only Scan", output:524288, filtered:0, rate:1.00000
           PlanNode[5] Indexscan is ought to be used:"Seq Scan", output:1, filtered:524288, rate:0.00000
   ```
   需要注意的是，这个诊断结果只是针对当前SQL的建议，是否创建索引要结合整体业务综合分析，对于高频的过滤条件才建议创建索引。
   
10. 估算不准
对于平均每DN行数如果优化器的估算行数和实际行数中的较大值大于10万行，并且估算行数和实际行数中较大值是较小值的10倍或以上，则上报相关告警。针对这种场景，可以参照[行数的Hint](https://support.huaweicloud.com/devg-dws/dws_04_0458.html)修正行数估算，让优化器在正确的行数基础上重新规划执行计划。
告警信息示例：
```
Execute diagnostic information
        PlanNode[5] Inaccurate Estimation-Rows: "Hash Join" A-Rows:0, E-Rows:52488
```
#### 规格约束
1. 告警字符串长度上限为2048。如果告警信息超过这个长度（例如存在大量未收集统计信息的超长表名，列名等信息）则不告警，只上报warning：
   ```
   WARNING, "Planner issue report is truncated, the rest of planner issues will be skipped"
   ```
   
2. 如果query存在limit节点（即查询语句中包含limit），则不会上报limit节点以下的Operator级别的告警。
3. 对于"数据倾斜"和"估算不准"两种类型告警，在某一个plan树结构下，只上报下层节点的告警，上层节点不再重复告警。这主要是因为这两种类型的告警可能是因为底层触发上层的。例如，如果在scan节点已经存在数据倾斜，那么在上层的hashagg等其他算子很可能也出现数据倾斜。
 
