SQL自诊断
用户在执行INSERT/UPDATE/DELETE/SELECT/MERGE INTO或者CREATE TABLE AS语句时,可能会遇到性能问题。产品内置集成了性能自动诊断功能,并把相关的诊断信息保存到实时TopSQL中,当配置参数enable_resource_track为on的时候,这些诊断信息会转存到历史TopSQL中。通过查询GS_WLM_SESSION_STATISTICS,GS_WLM_SESSION_HISTORY,GS_WLM_SESSION_INFO视图的warning字段可以获得对应的性能诊断信息,为性能调优提供参考。
- SQL自诊断的告警类型与resource_track_level的设置相关。
当“resource_track_level”设置为query时,可以诊断多列/单列统计信息未收集、分区未剪枝告警和SQL不下推的告警等非执行态的诊断信息;“resource_track_level”设置为perf或operator时,可以诊断所有的告警场景。
- SQL自诊断的诊断范围与resource_track_cost的设置相关。
当SQL的代价大于“resource_track_cost”时,SQL才会被诊断。SQL的代价可以通过explain来确认。
- 执行EXPLAIN PERFORMANCE或者EXPLAIN VERBOSE的时候,除缺乏多列统计信息之外的SQL自诊断信息也会输出,具体请参考SQL执行计划。
SQL执行性能相关告警场景
目前支持对以下10种导致性能问题的场景上报告警。
- 多列/单列统计信息未收集。
如果存在单列或者多列统计信息未收集,则上报相关告警。对于这种告警,建议的优化方案是对相关表进行ANALYZE,可参考更新统计信息和统计信息调优。
需要特别注意的是,如果查询语句中的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))
- 分区不剪枝。
分区表查询时,常会期望通过分区键上的约束条件进行分区剪枝,从而提升分区表查询性能,但有时候会因为约束条件书写不当,导致分区表没有剪枝,出现查询性能问题,具体请参见案例:改写SQL排除剪枝干扰。
- SQL不下推。
对于不下推的SQL,尽可能详细上报导致不下推的原因。调优方法可参考案例语句下推调优。
导致不下推的因素主要有以下两点:告警信息示例:
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
- 不支持向量化计划
对于不能走向量化计划的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
- HashJoin中大表做内表。
如果在表连接过程中使用了Hashjoin(可通过GS_WLM_SESSION_HISTORY的“query_plan”字段查看),且连接的内表行数是外表行数的10倍或以上;同时内表在每个DN上的平均行数大于10万行,且发生了下盘,则上报相关告警。针对这种场景,需要调整HashJoin内外表顺序,具体调优方法参考Join顺序的Hint。
告警信息示例:
Execute diagnostic information PlanNode[7] Large Table is INNER in HashJoin “Vector Hash Aggregate”
其中,7为“query_plan”字段文本中编号为7的算子。
- 大表等值连接使用Nestloop
如果在表连接过程中使用了nestloop(可通过GS_WLM_SESSION_HISTORY的query_plan字段查看),并且两个表中较大表的行数平均每个DN上的行数大于10万行、表的连接中存在等值连接,则上报相关告警。针对这种场景,需要调整表关联方式,禁止当前内外表之间使用NestLoop的关联方式,具体调优方法参考Join方式的Hint。
告警信息示例:
Execute diagnostic information PlanNode[5] Large Table with Equal-Condition use Nestloop"Nested Loop"
- 大表Broadcast
如果在Broadcast算子中,平均每DN的行数大于10万行,则告警大表Broadcast。针对这种场景,需要禁止Broadcast下层算子做Broadcast动作,具体调优方法参考Stream方式的Hint。
告警信息示例:
Execute diagnostic information PlanNode[5] Large Table in Broadcast "Streaming(type: BROADCAST dop: 1/2)"
- 数据倾斜
某表在各DN上的分布,存在某DN上的行数是另一DN上行数的10倍或以上,且有DN中的行数大于10万行,则上报相关告警。该告警一般分为存储层倾斜和计算层倾斜,具体调优方法参考数据倾斜调优。
告警信息示例:
Execute diagnostic information PlanNode[6] DataSkew:"Seq Scan", min_dn_tuples:0, max_dn_tuples:524288
- 索引不合理
- 对于行存表:
- 使用索引扫描,输出行数/扫描行数>1/1000且输出行数>1万行。
- 使用顺序扫描,输出行数/扫描行数<1/1000且输出行数<=1万行、扫描行数>1万行。
- 对于列存表:
- 使用索引扫描,输出行数/扫描行数>1/10000且输出行数>100。
- 使用顺序扫描,输出行数/扫描行数<1/10000且输出行数<=100、扫描行数>1万行。
调优方法可参考算子级调优,也可参考案例案例:建立合适的索引和案例:使用partial cluster key。
告警信息示例:
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的建议,是否创建索引要结合整体业务综合分析,对于高频的过滤条件才建议创建索引。
- 对于行存表:
- 估算不准
对于平均每DN行数如果优化器的估算行数和实际行数中的较大值大于10万行,并且估算行数和实际行数中较大值是较小值的10倍或以上,则上报相关告警。针对这种场景,可以参照行数的Hint修正行数估算,让优化器在正确的行数基础上重新规划执行计划。
告警信息示例:
Execute diagnostic information PlanNode[5] Inaccurate Estimation-Rows: "Hash Join" A-Rows:0, E-Rows:52488
规格约束
- 告警字符串长度上限为2048。如果告警信息超过这个长度(例如存在大量未收集统计信息的超长表名,列名等信息)则不告警,只上报warning:
WARNING, "Planner issue report is truncated, the rest of planner issues will be skipped"
- 如果query存在limit节点(即查询语句中包含limit),则不会上报limit节点以下的Operator级别的告警。
- 对于“数据倾斜”和“估算不准”两种类型告警,在某一个plan树结构下,只上报下层节点的告警,上层节点不再重复告警。这主要是因为这两种类型的告警可能是因为底层触发上层的。例如,如果在scan节点已经存在数据倾斜,那么在上层的hashagg等其他算子很可能也出现数据倾斜。