分布式
文章平均质量分 77
鸿乃江边鸟
Apache Spark Contributor
专注于技术的dotaer
展开
-
StarRocks 中如何做到查询超时(QueryTimeout)
通过本文的分析大致可以了解到在Starrocks的FE端是如何进行Command的交互以及数据流走向,其他的命令也是可以举一反三。和Spark以及hive等但是解析一样,StarRocks也是采用的Anltr4进行语法的解析,对应的java数据结构,但是一条SQL从客户端发送过来,是怎么一个数据流呢?操作的时候,就会根据执行的长短进行超时处理了。整体的数据流就结束了,待在同一个连接中进行。获取设置的超时时间,如果超时,则调用。中了,后续的流程和之前的一致。这种情况的解析,是通过。就会在语法层面解析为。原创 2024-10-01 15:48:51 · 703 阅读 · 0 评论 -
Spark AQE 导致的 Driver OOM问题
因为原则上来说,如果没有开启AQE之前,一个SQL执行单元的是属于同一个Job的,开启了AQE之后,因为AQE的原因,一个Job被拆成了了多个Job,但是从逻辑上来说,还是属于同一个SQL处理单元的所以还是得归属到一次执行中。类在内存中存放着 一个整个SQL查询链的所有stage以及stage的指标信息,在AQE中 一个job会被拆分成很多job,甚至几百上千的job,这个时候 stageMetrics的数据就会成百上倍的被存储在内存中,从而导致。主要的作用是设置当前计划的所属的。该方法会获取事件中的。原创 2024-04-26 22:39:30 · 1337 阅读 · 3 评论 -
Spark Rebalance hint的倾斜的处理(OptimizeSkewInRebalancePartitions)
假如说hash(col)为0,那实际上只有reduceTask0有数据,其他的ReduceTask1等等都是没有数据的,所以最终只有ReduceTask0写文件,并且只有一个文件。这些值配置,如果这些配置调整的不合适,就会导致写文件的时候有可能只有一个Task在运行,那么最终就只有一个文件。的作用是对小文件进行拆分,使得罗盘的文件不会太大,这个会有个问题,如果我们在使用。的作用主要是进行文件的合并,是得文件不会太小,本文基于Spark 3.5.0。的值是固定的,比如说值永远是。原创 2024-03-21 09:05:55 · 1143 阅读 · 0 评论 -
关于Spark中OptimizeShuffleWithLocalRead 中自己的一些理解
这种情况下,在Spark的内部表示 ShuffleOrigin 为 REBALANCE_PARTITIONS_BY_NONE,这种情况下 是hint为。这里的条件默认是根据shuffle的个数来计算的,如果优化后的shuffle数有增加,则会回退到之前的物理计划中去,当然用户也可以配置。针对第二种情况,这种情况一般来说都是有正向的提升效果的,但是也会经过第一种情况的逻辑判断。规则下,有可能会增加额外的Shuffle操作,这种情况就是负优化了,所以在进行了。的作用简单的来说,就是会按照一定的规则,从一个。原创 2024-03-06 22:58:52 · 815 阅读 · 0 评论 -
Spark中读parquet文件是怎么实现的
因为对于Spark来说,任何一个事情都不是独立的存在的,比如说parquet文件的rowgroup设置的大小对读写的影响,以及parquet写之前排序对读parquet的影响,以及向量化读取等等。为‘true’(默认就是true),则会进行unsafeRow的转换,当然这里的好处就是节约内存以及能够减少GC。最近在整理了一下 spark对Parquet的写文件的过程,也是为了更好的理解和调优Spark相关的任务,这条filter,则只会拿出rowgroup的信息和rowgrups的的行数。原创 2024-03-04 20:27:22 · 1112 阅读 · 0 评论 -
Spark中多分区写文件前可以不排序么
会根据partition或者bucket作为最细粒度来作为writer的标准,如果相邻的两条记录所属不同的partition或者bucket,则会切换writer,所以说如果不根据partition或者bucket排序的话,会导致。频繁的切换,这会大大降低文件的写入速度。目前 Spark中的实现中,对于多分区的写入默认会先排序,这是没必要的。至于Spark在写入文件的时候会加上Sort,这个是跟写入的实现有关的,也就是。这两个物理计划中,最终写入文件/数据的时候,会调用到。(默认值为0),则会加上。原创 2024-02-15 22:30:11 · 1039 阅读 · 0 评论 -
Spark调优案例分享
注意是Mac Keynote。原创 2023-11-13 20:15:49 · 941 阅读 · 0 评论 -
Spark 3.1.1 遇到的 from_json regexp_replace组合表达式慢问题的解决
最主要关心的是 parser这个变量,因为由于上述规则的原因,两个schema单独在不同的parser中,而这里的 Child是由regexp_replace表达式组成的,所以该正则表达式会计算两次,这里就会解析为 Alias(GetStructField(attribute.get, i), f.name)()(主要就是调用JsonToStructs.toString的方法)进行 UnresolvedStar 的expand方法的调用。主要的原因是 Spark 3.1.x 引入的。原创 2023-08-04 20:29:50 · 812 阅读 · 0 评论 -
Spark中为什么Left join比Full join 快
如果在语意允许的情况下,选择left join可以大大加速任务运行,笔者遇到的情况就是 left join 运行了。一样,唯一不一样的是SortMergeJoin 的child的outputPartitioning是。后如果不重新shuffle,会导致一个任务中会有id为null值的存在,会导致join的结果不正确。来说就不一样了,task join完后id还是保持原来的就不会变,所以就不必重新shuffle。只有在读取source文件完之后才会有Exchange的shuffle的操作。原创 2023-07-16 22:10:53 · 546 阅读 · 0 评论 -
Spark 3.4.0新特性--UI支持存储在RocksDB中
来说,目前存储所有的事件信息以及UI所需要的信息都是默认存储在内存中,这在CS中,对于以。作为存储以后,能够减少driver所需内存,并且引进新的。数据结构为InMemoryStore。能够大大加快spark事件的读写事件。Spark UI和SHS。原创 2023-07-01 15:39:00 · 1209 阅读 · 0 评论 -
SPARK中InMemoryFileIndex文件缓存导致的REFRESH TABLE tableName问题
其中cachedLeafDirToChildrenFiles的值会在InMemoryFileIndex对象初始化的时候进行赋值,对应的方法为。那是因为,在一个jvm中,比如说是写了之后再读取,会进行。的情况下,在转换对应的逻辑计划当中,如果缓存中存在对应的表,则会复用缓存中的,具体的方法在。的错误,这种错误的原因有一种隐形的原因,那就是。在scan file的过程中,最主要涉及的是。对象,从而实现了文件的复用,从未导致问题。会缓存需要scan的文件在内存中,中 ,最主要的点是会公用同一个。原创 2023-03-12 22:22:17 · 1462 阅读 · 0 评论 -
SPARK outputDeterministicLevel的作用--任务全部重试或者部分重试
方法的时候,如果任务发生了重试,就有可能导致任务的数据不准确,那这个时候改怎么解决这个问题呢?该方法主要用于在重新提交失败的stage时候,用来判断是否需要重新计算上游的所有任务。这里如果任务Fetch失败了,根据该shuffle所对应的上游stage是不是。方法是随机分配数据到下游,这会导致一个问题,有时候如果我们用。所以根据以上分析,我们可以改写对应的RDD的。那么该变量的作用是什么呢?方法进行上游所有任务或者单个任务的重试。方法来进行stage任务的全部重试与否。方法进行循环调用上游的。原创 2023-02-20 21:54:30 · 570 阅读 · 0 评论 -
Spark做TPC-DS性能测试
最近由于在做上云的工作,并且公司离线部分引擎是Spark,所以做了一次基于TPC-DS性能比对测试。生产了大约200GB的数据。原创 2023-01-31 22:05:23 · 2797 阅读 · 2 评论 -
Delta Lake中CDC的实现
根据以上的分析,可以知道目前的CDF只是在Delte层级做了反馈,如果说想要在Flink层达到CDC的效果,还得有个中间层,把delta里的CDF的数据给读取出来,转换Flink 内部形式的ChangelogMode CDC格式(比如说。CDF是能让表能够输出数据表变化的能力,CDC是能够捕获和识别数据的变化,并能够将变化的数据交给下游做进一步的处理。是判断过滤条件是否是在元数据层能够囊括,如果可以的话,就通过。我们来分析一下是怎么做到数据行级别的CDF的。这里列举该表的所有文件,并把所有的文件标识为。原创 2022-12-11 08:05:16 · 658 阅读 · 0 评论 -
SPARK中关于HighlyCompressedMapStatus的说明(会造成运行时的数据不精确)
这是来map端任务记录精确分区的阈值,如果大于该阈值,则会记录真实的reduce数据的分区大小,如果小于则记录的是每个reduce大小的平均值(这导致会在reduce获取运行时的数据大小信息时数据不准确的问题,从而导致AQE的效果不是很理想)。采用的是对于数据量小的reduce分区数据采用公用平均值的方式,这在一定程度上能够减缓Driver OOM的概率,中,这样下游的reduce任务如果需要获取上游MapTask的运行情况的时候就会最终调用到。因为对于小数据量的分区,只需要存储一个平均值,而不像。原创 2022-11-06 22:45:01 · 1396 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(10)
从一个unit test来探究SPARK Codegen的逻辑,本文基于 SPARK 3.3.0。原创 2022-09-20 12:29:26 · 223 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(9)
从一个unit test来探究SPARK Codegen的逻辑,sortAggregateExec的。本文基于 SPARK 3.3.0。updateExprs的不同。操作完后的结果buffer。其他的数据流向和之前的一样,方法,其中input为。阶段,所以更新语句是。原创 2022-09-20 12:28:41 · 874 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(8)
constructDoConsumeFunction方法中inputVarsInFunc。从一个unit test来探究SPARK Codegen的逻辑,本文基于 SPARK 3.3.0。根据数据类型的不同,调用。原创 2022-09-19 20:44:36 · 864 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(7)
val buffer = 和buffer.init(index, Array(iter))从一个unit test来探究SPARK Codegen的逻辑,对rdd进行迭代,对于当前的第一阶段全代码生成来说,该。代码进行编译,如果编译报错,则回退到原始的执行。代码初始化,对于当前第一阶段全代码生成来说,端进行编译,如果代码生成有误能够提前发现。(默认值),则回退到原始的执行。不会被用到,第二阶段中会把。不会被用到,因为数据是由。如果代码生成的长度大于。对于当前来说,目前只是。会被用来进行产生数据,原创 2022-09-18 22:53:45 · 512 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(6)
从一个unit test来探究SPARK Codegen的逻辑,本文基于 SPARK 3.3.0。中我们提到在对应的函数计算完后,是已经计算处理的结果了。的UnsafeRow。原创 2022-09-17 07:38:09 · 281 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(5)
是在SortAggregateExec的produce方法进行赋值的,也就是对应“SUM”和“COUNT”初始值的。传递进来了,但是在这个方法中却没有用到,因为对于大部分情况来说,该变量是对外部传递InteralRow的作用。,对于AVG聚合函数来说,聚合的缓冲属性(aggBufferAttributes)为。进行公共子表达式的消除,并提前计算出在计算子表达式计算之前的自表达式。对于当前的计划来说,SortAggregateExec的。本文基于 SPARK 3.3.0。对于目前的物理计划来说,当前的。原创 2022-09-15 20:32:27 · 776 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--GenerateUnsafeProjection.createCode说明
val writeFieldsCode =以及后面的代码组装。因为inputs的类型是LONG类型,所以对应到。因为inputs为null为false,所以。对每一个变量的赋值按照换行符进行分隔。对于在在RangeExec中出现的。原创 2022-09-14 20:18:58 · 510 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(4)
计算表达式的长度,对于LONG和DOUBLE类型长度为2,其他的为1,因为range_value_0是LONG类型,所以总的长度为3。不为空的情况下,则说明传入的是InteralRow类型的变量,需要调用InteralRow对应的方法获取对应的值。这部分是产生UnsafeRow类型的变量,这个UnsafeRow类型的变量里包含了rangExec的产生的变量。对于不是直接赋值的变量,而是通过计算得到的变量,则需要进行提前计算,在这里不需要计算。里面具体的细节,这里先忽略,以后会有具体的文章分析。原创 2022-09-13 23:24:49 · 406 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(3)
被赋值,这样父节点才能进行消费。值是用来表示rangExec生成的数据的,最终会被*consume(ctx, Seq(ev)val taskContext =和val inputMetrics =就是RangeExec生成数据的逻辑了,每个物理计划都是不一样。也是全部变量,而且还有初始化变量,这种初始化方法将会在生成的类方法。父节点进行消费rangeExec产生的数据,接下来会继续讲解。这部分就是根据每个分区的index不一样,生成不同的数据。是用来产生rangeExec数据的逻辑索引,遍历数据。原创 2022-09-09 00:03:16 · 364 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(2)
是对输出的数据进行组装,组装成UnsafeRow以便spark进行的后续处理,也就是在此以后返回的数据就是正常的InteralRow的处理方式了,对于*consume()*这部分代码我们后续再说,在这里我们先按照数据流的方式来解释代码。,如没特别说明,我们就只讲解AVG的代码生成部分,因为MAX等表达式原理是一样的。操作则是声明变量,这里的变量属于全局变量,也就是类的成员变量,前缀是当前类的前缀,具体是在。类型的变量,这样的话,就得调用InternalRow对应的方法获取对应的值,如。原创 2022-09-07 22:02:39 · 563 阅读 · 0 评论 -
SPARK中的wholeStageCodegen全代码生成--以aggregate代码生成为例说起(1)
看到这里的prefix = “”,所以单纯从执行计划看是没有任何迹象能表明存在着。但是实际在缕代码的时候,你就会发现这个全代码的逻辑根本就缕不通,那是因为。这种符号的,表明是有全代码生成的,而为什么在物理计划的时候没有显示。从一个unit test来探究SPARK Codegen的逻辑,,而这里的数字1和2代表者不同的两个代码生成阶段,因为。不支持代码生成,所以被隔离成了两个代码生成。本文基于 SPARK 3.3.0。作为子计划的前缀传递到了下游。计划是因为该两个计划重写了。原创 2022-09-02 09:26:17 · 860 阅读 · 0 评论 -
DATA AI Summit 2022提及到的对 aggregate 的优化
该优化的主要是partialaggregate的部分对于类似求count,sum,Avg的聚合操作,会存在现在mapper进行部分聚合的操作,之后在reduce端,再进行FinalAggregate操作。这看起来是没有问题的(能够很好的减少网络IO),但是我们知道对于聚合操作,我们会进行数据的spill的操作,如果在mapper阶段合并的数据很少,以至于抵消不了网络IO带来的消耗的话,这无疑会给任务带来损耗。利用运行时的指标信息,能够达到比较好的加速效果。但是这种在数据倾斜的情况下,会增加OOM的风险。..原创 2022-07-27 12:43:32 · 723 阅读 · 1 评论 -
SPARK中 DS V2 push down(下推)的一些说明
规则则是基于ScanBuilderHolder来做转换的(如果有遇到ScanBuilderHolder类型才会进行DSv2特有的规则转换),所以。我们有提到DSV2pushdown的功能,如JDBC复杂下推,以及Parquet的聚合下推等等。其实这里面有个比较大的背景–就是。类型,也就是DSv2,才会转换为ScanBuilderHolder,而后续的。本文基于SPARK3.3.0。一系列的规则中,第一个规则。.........原创 2022-07-24 09:56:57 · 816 阅读 · 0 评论 -
SPARK Parquet嵌套类型的向量化支持以及列索引(column index)
在Spark3.2.0之后,我们可以基于page级别的数据过滤(只选择需要的page),这样能大大减少IO,因为在page级别过滤的话,不需要每次都会获取整个Rowgroup的数据。在spark3.2.0之前Parquet的谓词下推是基于Rowgroup的统计信息来的,如最大最小值,字典信息,以及Parquet-1.12的Bloomfilter,根据以上的Parquet的格式存储,在读取的Parquet文件的时候,对于非向量化的读取,是一行一行的读取,支持所有类型,对于向量化的读取在。.........原创 2022-07-19 12:57:28 · 1333 阅读 · 0 评论 -
SPARK闲杂--为什么复用Exchange和subquery
只有开启了重用Exchange的情况下且存在物理计划是BroadcastHashJoinExec的情况下(只有这样才能获取最大的收益),才会进行动态分区裁剪。其实在这里并没有做过多的操作,只不过是生成了一个BroadcastExchangeExec的操作,看到这里完全没看出来重用Exchange的作用在哪里。中,这里会进行exchange的替换,如果存在一样的Exchange,就会进行替换,所以以上分区裁剪中的。也是lazyval,也是只会初始化一次,所以在。我们在Spark代码中有时候会看到。...原创 2022-07-15 21:01:17 · 702 阅读 · 0 评论 -
SPARK中的FileSourceStrategy,DataSourceStrategy以及DataSourceV2Strategy规则
本文基于SPARK 3.3.0用于记录Spark中V1和V2的Datasource以及FileSource的作用以及区别,以及在Spark 3.3.0出现的更强的Datasource v2 JDBC的下推在spark 3.3.0中 出现了DS V2 push down的功能,该功能是能够更好的进行下推,比如说更加复杂的聚合下推和过滤下推。涉及到filter过滤的地方为partitionKeyFilters 和dataFilters,partitionKeyFilters针对的是分区级别的过滤,比如说只选原创 2022-07-12 07:29:36 · 951 阅读 · 0 评论 -
SPARK最新特性Runtime Filtering(运行时过滤)以及与动态分区裁剪的区别
本文基于 SPARK 3.3.0在最新发布的SPARK RELEASE,第一个显著的特性就是row-level Runtime Filtering,我们来分析一下直接转到对应的 Jira SPARK-32268,里面涉及到的TPC benchmark,在数据行数比较大的情况下,BloomFilter带来的性能提升还是很明显的,最重要的设计文档在Row-level Runtime Filters in Spark,里面讲了两个关键点:该功能涉及到两个主要的Rule InjectRuntimeFilter和原创 2022-07-06 19:33:14 · 1755 阅读 · 1 评论 -
Spark 中的 Rebalance 操作以及与Repartition操作的区别
本文基本spark 3.2.1在Partitioning Hints Types中有提到Rebalance操作以及Repartition操作,而且他们都可以做数据的重分区,他们之间有什么区别呢?分析Rebalance参考对应的SPARK-35725,其目的是为了在AQE阶段,根据进行分区的重新分区,防止数据倾斜。再加上SPARK-35786,就可以根据hint进行重分区。具体看看怎么实现的,OptimizeSkewInRebalancePartitions代码如下:只有开启了 了的情况下,原创 2022-06-30 21:32:33 · 2137 阅读 · 0 评论 -
Flink 维表异步查询的实现以及问题排查
本文基于Flink 1.13.3Flink计算引擎VVR版本的hbase Connector具体maven依赖如下:在基于VVR版本的cloudHbase维表查询的时候,发现同步查询的速度很慢,所以我们打算做基于异步的维表查询。在运行的过程中发现了NPE问题,具体的报错堆栈如下:先说结论Flink计算引擎VVR版本的hbase Connector把hbase的数据转化为RowData的时候存在多线程问题,这种会导致NPE问题相比Asynchronous I/O for External Dat原创 2022-06-10 18:25:34 · 2304 阅读 · 0 评论 -
SPARK 3.1.2 Driver端下载UDF jar包导致磁盘爆满
本文基于spark 3.1.2且配置spark.sql.catalogImplementation=hive在以spark-sql形式运行sql任务时,发现运行driver端的机器的磁盘总是会达到95%以上的利用率.经过分析,我们发现是/tmp/${session_id}_resources下的UDF jar包导致的磁盘问题。这就使我们不得怀疑是调用hive的UDF函数造成的,接下来直接说重点,直接到ResolveFunctions Rule,改rule是用来解析函数的规则:这个函数最终会调用Sessi原创 2022-06-04 17:41:15 · 481 阅读 · 0 评论 -
SPARK的计算向量化-spark本身的向量化
背景我们知道,随着计算引擎战争的结束(SPARK赢得了离线处理的霸权),越来越多的公司致力于性能的优化,而引擎的优化,目前直指计算的向量化,这片文章来说说spark本身对于向量化的实现。spark本身的优化我们都知道spark的Tungsten项目,这个项目中有一点就是Code Generation(代码生成)。代码生成除了消除虚函数的调用等功能外,其实在向量化这块也是做了处理的。直接跳到ColumnarToRowExec代码:val columnarBatchClz = classOf[Col原创 2022-05-29 08:54:52 · 1209 阅读 · 0 评论 -
FLINK JDBC SQL Connector遇到的类型转换问题
背景Flink 1.3最近在写Flink Sql的时候,遇到了java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long 问题分析直接上报错的sql,如下:CREATE TABLE `xxx` ( `merchantId` BIGINT, `userId` BIGINT, `status` BIGINT) WITH ( );具体的问题堆栈如下:java.lang.C原创 2022-04-14 20:11:08 · 4342 阅读 · 0 评论 -
SPARK中 会对Scan的小文件做合并到一个Task去处理么?
背景本文基于SPARK 3.1.2在之前查看SQL物理计划的时候,发现一个很奇怪的现象,文件的个数很多,但是启动的Task却很少。结论SPARK在scan文件的时候,会把小文件合并到一个Task上去处理。分析这里的SQL很简单:就是select col from table语句我们直接查看对应的计划:可以看到对于有50000多个文件的source,最终却只有6000多个任务运行。我们直接看对应的代码FileSourceScanExec实现: val splitFiles = se原创 2022-04-03 12:06:21 · 2635 阅读 · 1 评论 -
SPARK 是怎么清除Shuffle中间结果数据的
背景本文基于 SPARK 3.2.1我们知道在Spark中,shuffle的数据会存在ESS或者BlockManager中的,但是spark什么时候会删除shuffle的中间结果数据呢?这篇文章我们来分析一下分析我们知道spark肯定会删除shuffle结果数据,要不然长期以往,磁盘肯定会爆掉。其中清除的组件就是ContextCleaner,代码如下:private[spark] class ContextCleaner( sc: SparkContext, shuffleDri原创 2022-04-01 19:57:59 · 3499 阅读 · 1 评论 -
SPARK push-based shuffle mapTask是怎么获取ESS列表信息
背景本文基于SPARK 3.2.1之前的文章SPARK SHUFFLE中 ShuffleId BlockManagerId 以及 与ESS(External Shuffle Server)交互,我们只是讲了一下大概的shuffle流程,这次来分析一下push-based shuffle,便于更好的理解spark shuffle中push-based shuffle.分析直接跳到ShuffleMapTask的RunTask方法:override def runTask(context: TaskC原创 2022-03-31 20:12:26 · 1280 阅读 · 0 评论