(六)一文掌握flink性能优化:flinksql调优

系列文章目录
第一章 资源配置调优
第二章 状态及Checkpoint 调优
第三章 反压处理
第四章 数据倾斜
第五章 job优化
第六章 flinksql调优
第七章 常见故障排查



FlinkSQL官网配置参数:https://nightlies.apache.org/flink/flink-docs-release-1.13/docs/dev/table/config/

6.1 设置 空闲状态保留时间

Flink SQL新手有可能犯的错误,其中之一就是 忘记设置空闲状态保留时间导致状态爆炸。列举两个场景:

  • FlinkSQL 的 regu lar join inner 、 left 、 right ),左右表的数据都会 一直保 存在
    状态里,不会清理!要么设置 TTL ,要么使用 Flink SQL 的 interval join 。
  • 使用 Top N 语法进行去重,重复数据的出现一般都位于特定区间内(例如一小时
    或一天内),过了这段时间之后,对应的状态就不再需要了。

Flink SQL可以指定空闲状态(即未更新的状态)被保留的最小时间 当状态中某个 key
对应的 状态 未更新的时间达到阈值时,该条状态被自动清理

//API 指定
tableEnv.getConfig().setIdleStateRetention(Duration.ofHours(1));
//参数指定
Configuration configuration = tableEnv.getConfig().getConfiguration();
configuration.setString("table.exec.state.ttl", "1h");

6.2 开启 MiniBatch

MiniBatch是微批处理,原理是 缓存一定的数据后再触发处理,以减少对 State 的访问从而提升吞吐并减少数据的输出量。MiniBatch主要依靠在每个Task上注册的Timer线程来触发微批,需要消耗一定的线程调度性能。

  • MiniBatch 默认关闭,开启方式如下
// 初始化 table environment
TableEnvironment tEnv = ...
// 获取 tableEnv 的配置对象
Configuration configuration = tEnv.getConfig().getConfiguration();
// 设置参数:
开启 miniBatch
configuration.setString("table.exec.mini-batch.enabled", true);
批量输出的间隔时间
configuration.setString("table.exec.mini-batch.allow-latency", 5s);
防止 OOM 设置每个批次最多缓存数据的条数 ,可以设为 2 万条
configuration.setString("table.exec.mini batch.size", 20000);
  • 适用场景

微批处理通过增加延迟换取高吞吐,如果有超低延迟的要求,不建议开启微批处理。通
常对于聚合的场景,微批处理可以显著的提升系统性能,建议开启。
在这里插入图片描述

  • 注意事项:
    1、目前, key value 配置项仅被 Blink planner 支持。
    2、1.12 之前的版本有 bug ,开启 miniBatch ,不会清理过期状态,也就是说如果设置状态的 TTL ,无法清理过期状态。 1.12 版本才修复这个问题 。参考ISSUE: https://issues.apache.org/jira/browse/FLINK 17096

6.3 开启 LocalGlobal

原理概述
LocalGlobal优化将原先的 Aggregate 分成 Local+Global 两阶段聚合,即MapReduce 模型中的 Combine+Reduce 处理模式。第一阶段在上游节点本地攒一批数据进行聚合( localAgg ),并输出这次微批的增量值 A ccumulator )。第二阶段再将收到的 Accumulator 合并( Merge ),得到最终的结果 GlobalAgg )。

LocalGlobal本质上能够靠 LocalAgg 的聚合筛除部分倾斜数据,从而降低 GlobalAgg的热点,提升性能。结合下图理解 LocalGlobal 如何解决数据倾斜的问题。
在这里插入图片描述
由上图可知:

  • 未开启 LocalGlobal 优化,由于流中的数据倾斜, Key 为红色的聚合算子实例需要处理更多的记录,这就导致了热点问题。
  • 开启 LocalGlobal 优化后,先进行本地聚合,再进行全局聚合。可大大减少 GlobalAgg的热点,提高性能。

LocalGlobal 开启方式:
1)LocalGlobal 优化需要先开启 MiniBatch ,依赖于 MiniBatch 的参数。
2)table.optimizer.agg phase strategy : 聚合策略。默认 AUTO ,支持参数 AUTO 、TWO_PHASE( 使用 LocalGlobal 两阶段聚合 、 ONE_PHASE( 仅使用 Global 一阶段聚合)。

// 初始化 table environment
TableEnvironment tEnv = ...
// 获取 tableEnv 的配置对象
Configuration configuration = tEnv.getConfig().getConfiguration();
// 设置参数:
//开启 miniBatch
configuration.setString("table.exec.mini-batch.enabled",true);
//批量输出的间隔时间
configuration.setString("table.exec.mini-batch.allow-latency ", "5s");
//防止 OOM 设置每个批次最多缓存数据的条数 ,可以设为 2 万条
configuration.setString("table.exec.mini-batch.size", "20000");
// 开启 LocalGlobal
config uration.setString("table.optimizer.agg-phase-strategy", "TWO_PHASE");

注意事项:
1)需要先开启 MiniBatch
2)开启 LocalGlobal 需要 UDAF 实现 Merge 方法 。

提交案例:统计每天每个 mid 出现次数

在这里插入图片描述
可以看到存在数据倾斜。

提交案例:开启 miniBatch 和 LocalGlobal
在这里插入图片描述
从WebUI 可以看到分组聚合变成了 Local 和 Global 两部分, 数据相对均匀,且没有数据倾斜。

6.4 开启 Split Distinct

LocalGlobal优化针对普通聚合(例如 SUM 、 COUNT 、 MAX 、 MIN 和 AVG )有较好的效果,对于 DISTINCT 的聚合(如 COUNT DISTINCT 收效不明显,因为 COUNT DISTINCT 在 Local 聚合时,对于 DISTINCT KEY 的去重率不高,导致在 Global 节点仍然存在热点。

原理概述

之前,为了解决COUNT DISTINCT 的热点问题,通常需要手 动改写为两层聚合(增加按 Distinct Key取模的打散层)。

从 Flink1.9.0 版本开始,提供了 COUNT DISTINCT 自动打散功能, 通过HASH_CODE(distinct_key) % BUCKET_NUM 打散,不需要手动重写。Split Distinct 和LocalGlobal 的原理对比参见下图。
在这里插入图片描述
Distinct举例

SELECT a,COUNT(DISTINCT b
FROM T
GROUP BY a

手动打散举例

SELECT a,SUM(
FROM (
	SELECT a,COUNT(DISTINCT b ) as cnt
	FROM T
	GROUP BY a,MOD(HASH_ b),
GROUP BY a

Split Distinct 开启方式

默认不开启,使用参数显式开启

  • table.optimizer.distinct agg.split.enabled: true 默认 false 。
  • table.optimizer.distinct agg.split.bucket num: Split Distinct 优化在第一层聚合中,被打散的bucket 数目。默认 1024。
// 初始化 table environment
TableEnvironment tEnv = ...
// 获取 tableEnv 的配置对象
Configuration configuration = tEnv.getConfig().getConfiguration();
// 设置参数: 要结合 minibatch 一起 使用
//开启 Split Distinct
configuration.setString(" table.optimizer.distinct agg.split.enabled", "true");
//第一层 打 散 的 bucket 数目
configuration.setString(" table.optimizer.distinct agg.split.bucket num", "1024");

注意事项:
(1)目前不能在包含 UDAF 的 Flink SQL 中使用 Split Distinct 优化方法。
(2)拆分出来的两个 GROUP 聚合还可参与 LocalGlobal 优化。
(3)该功能在 Fl ink1.9.0 版本 及以上版本才支持。

提交案例: count ( 存在热点问题)

在这里插入图片描述
提交案例:开启 split distinct
在这里插入图片描述
从WebUI 可以看到有两次聚合,而且有 partialFinal 字样,第二次聚合时已经均匀 。

6.5 多维 DISTINCT 使用Filter

在某些场景下,可能需要从不同维度来统计count distinct )的结果 (比如统计 uv 、app 端的 uv 、 web 端的 uv 可能会使用如下 CASE WHEN 语法 。

SELECT
  a,
  COUNT(DISTINCT b ) AS total_ b,
  COUNT(DISTINCT CASE WHEN c IN (' A ', B ') THEN b ELSE NULL END) AS AB b,
  COUNT(DISTINCT CASE WHEN c IN (' C ', D ') THEN b ELSE NULL END) AS CD_b
FROM T
GROUP BY a

在这种情况下,建议使用FILTER 语法 , 目前的 Flink SQL 优化器可以识别同一唯一键上的不同 FILTER 参数。如,在上面的示例中,三个 COUNT DISTINCT 都作用在 b 列上。此时,经过优化器识别后,Flink 可以只使用一个共享状态实例,而不是三个状态实例,可减少状态的大小和对状态的访问。

将上边的CASE WHEN 替换成 FILTER 后 ,如下所示:

SELECT
	a,
	COUNT(DISTINCT b ) AS b,
	COUNT(DISTINCT b ) FILTER (WHERE c IN (' A ', B ')) AS AB_b,
	COUNT(DISTINCT b ) FILTER (WHERE c IN (' C ', D ')) AS CD b
FROM T
GROUP BY a

提交案例 :多维 Distinct

在这里插入图片描述

提交案例: 使用 Filter

在这里插入图片描述
通过WebUI 对比 前 1 0 次 Checkpoint 的大小,可以看到 状态 有所减小。

6.6设置参数总结

总结以上的调优参数,代码如下:

// 初始化 table environment
TableEnvironment tEnv = ...
// 获取 tableEnv 的配置对象
Configuration configuration = tEnv.getConfig().getConfiguration();
// 设置参数:
//开启 miniBatch
configuration.setString("table.exec.mini batch.enabled", "true");
//批量输出的间隔时间
configuration.setString("table.exec.mini batch.allow latency", "5s");
//防止 OOM 设置每个批次最多缓存数据的条数 ,可以设为 2 万条
configuration.setString("table.exec.mini-batch.size", "20000");
// 开启 LocalGlobal
configuration.setString("table.optimizer.agg-phase-strategy", "TWO_PHASE");
//开启 Split Distinct
configuration.setString("table.optimizer.distinct-agg.split.enabled", "true"); 
//第一层 打 散 的 bucket 数目
configuration.setString("table.optimizer.distinct-agg.split.bucket-num", "1024");
//指定时区
configuration.setString("table.local-time-zone", "Asia/Shang hai");
  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: SparkSQLFlinkSQL和HiveSQL是三种不同的SQL查询引擎,它们都可以用于处理大规模数据。它们的性能对比如下: 1. SparkSQL:SparkSQL是基于Spark计算引擎的SQL查询引擎,它可以处理大规模数据,并且具有很好的性能。SparkSQL的优点在于它可以利用Spark的分布式计算能力,可以在内存中缓存数据,从而提高查询速度。但是,SparkSQL的缺点在于它的启动时间比较长,而且在处理小规模数据时,性能不如其他两种SQL查询引擎。 2. FlinkSQLFlinkSQL是基于Flink计算引擎的SQL查询引擎,它也可以处理大规模数据,并且具有很好的性能。FlinkSQL的优点在于它可以利用Flink的流式计算能力,可以实时处理数据,并且可以在内存中缓存数据,从而提高查询速度。但是,FlinkSQL的缺点在于它的学习曲线比较陡峭,需要一定的学习成本。 3. HiveSQL:HiveSQL是基于Hadoop计算引擎的SQL查询引擎,它也可以处理大规模数据,但是性能相对较差。HiveSQL的优点在于它可以利用Hadoop的分布式计算能力,可以处理大规模数据,并且可以与其他Hadoop生态系统工具无缝集成。但是,HiveSQL的缺点在于它的查询速度比较慢,因为它需要将SQL语句转换为MapReduce任务进行处理。 综上所述,SparkSQLFlinkSQL在处理大规模数据时具有更好的性能,而HiveSQL则适用于与Hadoop生态系统工具集成的场景。 ### 回答2: SparkSQLFlinkSQL和HiveSQL都是基于SQL的数据处理引擎,它们都能够处理大规模数据。但是它们的性能和适用场景有所不同。 首先,SparkSQL是Apache Spark的一部分,它是一种非常流行的大数据处理引擎。SparkSQL具有良好的可扩展性和容错性,能够处理大规模且复杂的数据处理任务。但是,在处理小数据量时,SparkSQL的性能不如其他引擎,因为它要启动整个Spark应用程序来处理数据。 其次,FlinkSQL是Apache Flink的一部分,它是一种新兴的流式处理引擎。FlinkSQL是基于流处理的,能够实时处理数据,因此它适合处理实时流式数据。FlinkSQL的性能在流式数据处理方面非常出色,在处理批量数据时也比SparkSQL和HiveSQL更快。 最后,HiveSQL是Apache Hive的一部分,它是基于Hadoop平台的数据处理引擎。HiveSQL是一种批量处理引擎,适合处理大规模的离线数据。HiveSQL的性能在处理此类数据时非常出色,因为它能够利用Hadoop的分布式计算能力,但是在处理实时数据时性能较差。 总的来说,三个SQL引擎都有自己的优势和缺点,选择适合自己业务场景的引擎非常重要。如果需要处理实时流数据和批量数据,则可以选择FlinkSQL;如果需要处理离线批量数据,则可以选择HiveSQL;如果需要处理大规模和复杂的数据,则可以选择SparkSQL。 ### 回答3: SparkSQL FlinkSQL HiveSQL都是目前业内广泛使用的三种SQL查询引擎,均被称为大数据处理的利器。虽然三者都能支持SQL查询,但是它们的实现方式和效率是不同的。 首先是SparkSQL。SparkSQL 作为 Apache Spark 的组件,是在 Spark 引擎上实现 SQL 查询的工具。SparkSQL 是 Apache Spark 的 SQL 引擎,充分利用了 Spark 引擎的内存计算能力和分布式计算能力,因此可以快速高效地进行数据处理和分析。同时,SparkSQL 支持多种数据源,包括 HDFS、Hive、JSON、Parquet 等,还可以与 Spark Streaming 直接集成,支持流处理。 然后是FlinkSQLFlinkSQL 是 Apache Flink 提供的查询引擎,主要是基于 Flink 所提供的流式计算引擎。相比于 SparkSQLFlinkSQL 相对年轻和比较新颖。但是 FlinkSQL 在流式计算和 batch 计算都有着良好的性能表现,并且还支持 SQL 标准语言 ANSI SQL,具有较好的兼容性。 最后是HiveSQL。HiveSQL 是基于 Hadoop 生态圈的数据仓库系统,旨在为 Hadoop 带来类似于 SQL 的查询功能,以提高数据分析的效率。在 HiveSQL 中,数据存储在 HDFS 中而不是传统的关系型数据库中。相比于 SparkSQLFlinkSQL,HiveSQL 操作数据时,会将查询转换为 MapReduce 作业或者 Tez DAG 作业,这种转换导致了不可避免的性能损失,性能不如 FlinkSQL 和 SparkSQL。 综上所述,三种SQL查询引擎的性能表现可以总结如下: 1. 对于离线批处理,HiveSQL 有着较好的表现。但是在不断发展的大数据处理场景中,HiveSQL 已经不能满足实时计算的要求。 2. FlinkSQL 和 SparkSQL 在处理流数据时都有着不错的表现,但是 FlinkSQL 相对较新,所以在某些特殊场景下 SparkSQL 更加适合。 3. 对于实时计算而言,FlinkSQL 是一个不错的选择,因为 FlinkSQL 有着相对比较好的复杂流数据的处理能力。 总之,选择哪种 SQL 查询引擎,需要根据具体的数据处理场景和业务需求来选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值