自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(169)
  • 收藏
  • 关注

原创 Spark关于 ExpressionEncoder[T] 以及 RowEncoder 以及Spark怎么做外部数据和内部数据的转换

该方法,该方法是用来把表示涉及的属性,给映射到对应的计划的属性值上,这样我们计算的时候,就可以获取到对应的值,一般是调用。这里会涉及到两个ROW的转换,两个ROW的 Schema 是不一致的,如果要涉及到两个ROW之间的转换的时候,而且。的值,所以get(0)是 GenericRowWithSchema类型的ROW,也就是ROW类型。, 前者是 Spark 内部的使用的一行数据的表示,后者是给Spark开发者使用的行数据表示。可执行表达式,最最终绑定到表的特定属性上,从而获取对应的值。

2024-06-05 16:49:29 580 1

原创 记一次Spark cache table导致的数据问题以及思考

这会导致shuffle后的数据进行了错位(因为之前是shuffle(200),现在变成了shuffle(10)),具体原因笔者还是没有分析清楚,但是其中涉及到的点跟规则。从以上的分析知道:是在做join的一方(包含了AQEshuffleRead-coalesced) 影响了join的另一方,导致。目前在做 Spark 升级(3.1.1升级到3.5.0)的时候,遇到了。导致的数据重复问题,这种情况一般来说是很少见的,因为一般很少用。会做一些执行前的判断,主要是做任务shuffle的协调,

2024-05-22 19:54:53 367

原创 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 1202 3

原创 Spark Rebalance hint的倾斜的处理(OptimizeSkewInRebalancePartitions)

假如说hash(col)为0,那实际上只有reduceTask0有数据,其他的ReduceTask1等等都是没有数据的,所以最终只有ReduceTask0写文件,并且只有一个文件。这些值配置,如果这些配置调整的不合适,就会导致写文件的时候有可能只有一个Task在运行,那么最终就只有一个文件。的作用是对小文件进行拆分,使得罗盘的文件不会太大,这个会有个问题,如果我们在使用。的作用主要是进行文件的合并,是得文件不会太小,本文基于Spark 3.5.0。的值是固定的,比如说值永远是。

2024-03-21 09:05:55 991

原创 Spark中InsertIntoHiveTable 和 InsertIntoHadoopFsRelationCommand(两种写hive的方式)区别和注意的点

目前Spark写hive表有两种形式,一种是基于 Hive 原生的模式,一种是Spark native datasource的模式, 这两种模式可以通过配置的参数。方法的过程,尤其如果说是已存在的hive表有百万分区的话,很容易造成。,该方法会从把hive中的properties的信息传给。,这个方法如果对于分区数比较多的情况下是比较耗时的,而且。对于第一种原生的hive写入方式来说,最终调用的是。中的方法,里面采用的是spark自身的进行写入。中的方法,而这里面的都是采用。本文基于Spark 3.5。

2024-03-08 17:14:41 973

原创 关于Spark中OptimizeShuffleWithLocalRead 中自己的一些理解

这种情况下,在Spark的内部表示 ShuffleOrigin 为 REBALANCE_PARTITIONS_BY_NONE,这种情况下 是hint为。这里的条件默认是根据shuffle的个数来计算的,如果优化后的shuffle数有增加,则会回退到之前的物理计划中去,当然用户也可以配置。针对第二种情况,这种情况一般来说都是有正向的提升效果的,但是也会经过第一种情况的逻辑判断。规则下,有可能会增加额外的Shuffle操作,这种情况就是负优化了,所以在进行了。的作用简单的来说,就是会按照一定的规则,从一个。

2024-03-06 22:58:52 720

原创 Spark中读parquet文件是怎么实现的

因为对于Spark来说,任何一个事情都不是独立的存在的,比如说parquet文件的rowgroup设置的大小对读写的影响,以及parquet写之前排序对读parquet的影响,以及向量化读取等等。为‘true’(默认就是true),则会进行unsafeRow的转换,当然这里的好处就是节约内存以及能够减少GC。最近在整理了一下 spark对Parquet的写文件的过程,也是为了更好的理解和调优Spark相关的任务,这条filter,则只会拿出rowgroup的信息和rowgrups的的行数。

2024-03-04 20:27:22 1032

原创 Spark中写parquet文件是怎么实现的

的时候得注意不能调整过大,否则会导致OOM,但是如果在最后写文件的时候加入合并小文件的功能(AQE+Rebalance的方式),也可以适当的调整大一点,因为这个时候的Task 不像没有shuffle一样,可能还会涉及到sort以及aggregate等消耗内存的操作,(这个时候就是一个task纯写parquet文件)这三个配置项存在着相互制约的关系,总的目标就是检查当行数达到了一定的阈值以后,来检查是否能够flush到内存page中,具体的可以查看。表示的是partition名字的常量。

2024-02-22 22:53:08 1258

原创 Spark中多分区写文件前可以不排序么

会根据partition或者bucket作为最细粒度来作为writer的标准,如果相邻的两条记录所属不同的partition或者bucket,则会切换writer,所以说如果不根据partition或者bucket排序的话,会导致。频繁的切换,这会大大降低文件的写入速度。目前 Spark中的实现中,对于多分区的写入默认会先排序,这是没必要的。至于Spark在写入文件的时候会加上Sort,这个是跟写入的实现有关的,也就是。这两个物理计划中,最终写入文件/数据的时候,会调用到。(默认值为0),则会加上。

2024-02-15 22:30:11 977

原创 Spark UI中 Shuffle Exchange 和 BroadcastExchange 中的 dataSize 值为什么不一样

两个同样的 ShuffleExechange 记录条数和 ShuffleExechange 中 datasize 大小不一样,而在BroadcastExechange 中 dataSize 大小却是一样的(都是64.5MB)而该size的大小并不是实际占用的大小,而是分配给该dataPage的大小。中的是 MemoryBlock 类型数据结构所占的大小 ,而不是UnsafeRow的大小。中的datasize大小 和 2的整数倍接近。中的是真实 UnsafeRow的大小。的大小几乎和2的倍数接近。

2024-01-22 20:54:41 583

原创 Spark在降本增效中的一些思考

这也是笔者一直在关注的项目,根据 TPC-H 测试结果显示起码有2倍的性能提升,但是实际效果还是得看SQL的pattern。但是由于目前我们的Spark 是基于 3.5.0的,是比较新的版本,而社区这块的融合还在继续,所以这块今年应该可以行动起来,可以参考。注意: 我们批集群的CPU利用率在60%以上,引入zstd以后会增加CPU的使用率,而且在这种 long running的服务下,得增加。,但是这里请注意一点,该问题的提出点是基于 HDD 类型的磁盘的,因为我们现在是基于。

2024-01-19 09:03:16 1062

原创 Spark 中 BroadCast 导致的内存溢出(SparkFatalException)

这个问题折腾了我大约2个小时,错误发生的上下文都看了不止十遍了,还是没找到一丝头绪,可能是上帝的旨意,在离错误不到50行的地方,对于一个在大数据行业摸爬滚打了多年的老手来说,第一眼肯定是跟着堆栈信息进行排查,目前在排查 Spark 任务的时候,遇到了一个很奇怪的问题,在此记录一下。在查找错误的时候,还是得在错误的上下文中多翻几页。这个类,但是就算把代码全看一遍也不会有所发现。, 没想到是 OOM 问题。理所当然的就是会找到。

2024-01-08 17:57:35 839

原创 Spark Paimon 中为什么我指定的分区没有下推

针对于错误的写法,也就是导致读取全量数据的写法,我们分析一下,首先是类型转换阶段,在Spark中,对于类型不匹配的问题,spark会用规则进行转换,具体的规则是。最近在使用 Paimon 的时候遇到了一件很有意思的事情,写的 SQL 居然读取的数据不下推,明明是分区表,但是却全量扫描了。这种情况下,对于文件的读取IO会增大,但是对于shuffle等操作是不会有性能的影响的。对于分区字段来说,我们在写SQL对分区字段进行过滤的时候,保持和分区字段类型一致。可以看到经过了规则转换 所有的过滤条件都下推到了。

2023-12-14 18:02:27 745

原创 Spark升级中对log4j的一些思考

最终我们只留下了log4j2 (log4j-core + log4j-api) + logback (logback-classic + logback-core) ,其他的都排除掉,web端打包加编译没有任何问题,一切还是那么的美好(毕竟花了一天时间)在 spark3.1中采用的是log4j1 (log4j + slf4j-log4j2),spark 3.5中采用的是log42(log4j-core + log4j-api + log4j-slf4j2-impl),

2023-11-27 23:25:11 1277

原创 Spark调优案例分享

注意是Mac Keynote。

2023-11-13 20:15:49 903

原创 Apache Arrow优点

优点采用连续的内存布局,在单机计算的时候,增加操作系统友好性,增加了缓存命中率以及采用列式存储,在单机计算的时候,可以利用SMID向量化处理,并且增加了查询效率(一般查询的时候只是查询几列)采用列式存储,IPC进程间通信传输的时候,提高了压缩率采用零拷贝,IPC进程间通信传输的时候,减少了数据传输的开销跨语言的标准化规范,消除了各个格式之间转换所需要的序列化和反序列化的时间以上优点实现了高速的数据传输和处理能力,使得它在大数据场景下有很好的优化价值参考Apache Arrow: 数据工

2023-11-10 16:31:16 241

原创 Spark UI中Shuffle dataSize 和shuffle bytes written 指标区别

目前在做一些知识回顾的时候,发现了一些很有意思的事情,就是Spark UI中ShuffleExchangeExec 的dataSize和shuffle bytes written指标是不一样的,指的是写入文件的字节数,会区分压缩和非压缩,如果在开启了压缩(也就是spark.shuffle.compress true)和未开启压缩的情况下,该值的大小是不一样的。那么在AQE阶段的时候,是以哪个指标来作为每个Task分区大小的参考呢。的实例,这样就获取到了实际内存中的每个分区的大小,

2023-10-27 07:38:47 731

原创 Flink 中kafka broker缩容导致Task一直重启

(默认30000),这两个参数来控制kakfa的客户端从服务端请求超时,也就是说每次请求的超时时间是30s,超时之后可以再重试,如果在60s内请求没有得到任何回应,则会报。这里做的事情就是从持久化的State中恢复kafkaTopicOffset信息,我们这里假设是第一次启动。获取到要提交的kafka offset信息,并持久化保存kafka中。在Flink中对于Kafka的Connector的。,这里我们只讨论kafka作为source的情况,方法会被调用,所有kafka相关的操作都可以追溯到。

2023-10-12 11:28:35 1124

原创 Apache Hudi初探(五)(与flink的结合)--Flink 中hudi clean操作

首先是反序列化CleanPlan,然后在进行清理,主要是删除1. 如果没有满足的分区,直接删除该分区,2. 否则删除该分区下的满足条件的文件,最后返回。HoodieFlinkMergeOnReadTable*类型的hudi表,用来做clean等操作。,也就是在写数据失败的时候,会立即进行这次写失败的数据的清理,在这种情况下,创建一个只有一个线程的线程池,改线程池的主要作用来异步执行hudi写操作。本文主要是具体说说Flink中的clean操作的实现。真正执行clean的部分,主要是调用。

2023-09-27 13:01:49 1191

原创 Apache Hudi初探(四)(与flink的结合)--Flink Sql中hudi的createDynamicTableSource/createDynamicTableSink/是怎么被调用

最终会调用catalogManager.registerCatalog方法,用catalogManager管理了起来,这样在用到的时候就会调用该get方法得到对应的catalog。来说明一下Flink中createDynamicTableSource/createDynamicTableSink/createCatalog是什么时候被调用的。也说该方法的调用是在逻辑生成阶段的.(createDynamicTableSource方法的调用逻辑也是一样的)对应到SQL中的调用逻辑为。

2023-09-08 18:02:58 216 1

原创 Apache Hudi初探(三)(与flink的结合)--flink写hudi的操作(真正的写数据)

在之前的文章中Apache Hudi初探(二)(与flink的结合)–flink写hudi的操作(JobManager端的提交操作) 有说到写hudi数据会涉及到写hudi真实数据以及写hudi元数据,这篇文章来说一下具体的实现这里的操作就是在HoodieFlinkWriteClient.upsert方法:initTable初始化HoodieFlinkTablepreWrite在这里几乎没什么操作getOrCreateWriteHandle创建一个写文件的handle(假如这里创建的是Flin

2023-08-31 23:24:55 803

原创 Apache Hudi初探(二)(与flink的结合)--flink写hudi的操作(JobManager端的提交操作)

在Apache Hudi初探(一)(与flink的结合)中,我们提到了,这个操作真正写hudi是在方法下的,具体分析一下写入的过程。对于这个代码片段,我们主要看 这个对象(这个操作是Flink框架的操作):最主要的算子为,其中最主要的操作是由来完成的:操作,主要是做一些初始化的操作获取当前的task的索引下标,用来向发送event给,之后 StreamWriteOperatorCoordinator() 进行处理,后续会说到StreamWriteOperatorCoordinator初始化hu

2023-08-21 22:14:56 2140

原创 Spark 3.4.x 对 from_json regexp_replace组合表达式慢问题的解决

该计划的差异主要部分还是在于Rule在和的差别处理。

2023-08-12 16:44:47 432

原创 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 731

原创 Spark SQLHadoopMapReduceCommitProtocol中mapreduce.fileoutputcommitter.algorithm.version选择1还是2

大概的意思因为要保证task commits的原子性,所以好的建议是remove掉v2,不推荐使用V2。所以最后得出的结论就是:V1是安全的,但是性能不好,V2有可能是不安全的,但是性能好,推荐使用V1。FileOutputCommitter.commitTask方法。也就是为了保证spark向前向后的兼容性,强行设置为。dataWriter.write和commit方法。该executeTask方法最后会调用。当然Spark官方文档也有解释。对于spark来说默认的。更多关于细节,可以参考。

2023-08-02 23:20:14 308

原创 Apache Hudi初探(十一)(与spark的结合)--hudi的markers机制

虽然说在Executor端写入了多个重复数据的文件,但是因为在只有一个真正的文件会被Driver认可,所以通过最终返回的被driver认可的文件和marker文件求交集就能删除掉其他废弃的文件。在写入真正文件的同时,会在 .hoodie/.temp/instantTime目录下创建maker文件,比如.hoodie/.temp/202307237055/f1.parquet.marker.CREATE,之后在task.commit的时候会把临时目录的文件真正的移到需要写入的目录下。

2023-07-23 10:24:06 220

原创 Apache Hudi初探(十)(与spark的结合)--hudi的Compaction操作

这步操作主要是把生成的Compaction plan序列化成字节,并保存在相应的文件中,并生成一个Compaction的Request。baseFile,partitionPath,logFiles,还有Compaction策略。该方法主要是生成一个调度Compaction的计划。执行当前Commit的compaction操作。重新运行上次失败的Compaction计划。是够是异步Compaction计划生成。中,我们没有过多的解释Spark中。的实现,在这里详细说一下。

2023-07-22 16:57:01 483

原创 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 450

原创 Spark k8s Scheduler(Apache YuniKorn and Volcano)杂谈

毕竟k8s一开始的就是只是支撑online服务的,并不是用来做批调度的,当然这就存在问题了,在真实线上环境的时候,需要被调度的pod很可能是一下就来了几千个,这种情况下会发现,你的任务一直处于被调度的状态。的支持功能很不完善,笔者遇到的问题就是,所有的spark driver都提交上去了,但是却没没有获得pod去启动executor,导致任务运行很长。出现,是为了让k8s的调度更加像Yarn的调度一样,让使用yarn的用户能够无缝的切换到k8s中去。一开始的时候,k8s的内部调度的吞吐是很慢的。

2023-07-09 16:43:56 1017

原创 Delta数据湖upsert调优---1000多列表的调优

最终会调用反射去获取字段,要知道反射是比较消耗时间的,要知道我们现在是有1000多个字段,如果每一行都会被反射1000次,再加上几十亿行的数据,这个计算速度肯定是比较慢的,而且为了达到更新的效果,我们还调用了。目前在我们公司遇到了一个任务写delta(主要是的。delta的MergeIntoCommand。操作,这又增加了cpu的计算(1000多次)set该schema的字段,其他的字段不变。实现的,该操作的的具体实现,可以参考。操作),写入的时间超过了。

2023-07-04 23:49:27 270

原创 Spark 3.4.0新特性--UI支持存储在RocksDB中

来说,目前存储所有的事件信息以及UI所需要的信息都是默认存储在内存中,这在CS中,对于以。作为存储以后,能够减少driver所需内存,并且引进新的。数据结构为InMemoryStore。能够大大加快spark事件的读写事件。Spark UI和SHS。

2023-07-01 15:39:00 1066

原创 Spark 3.4.x Server Client模式下的数据传输实现

中,我们提到Spark 3.4.x中是Client和Server之间的数据传输是采用。的,那具体是怎么实现的呢?这里的逻辑就是转换为。

2023-06-27 23:17:43 341

原创 Flink中KeyedStateStore实现--怎么做到一个Key对应一个State

所对应的所有的values,也就是* Flink中的Key-Groups*,(关于Key-Groups可以参考。,从网上随便查找资料就能发现正确的答案是:对于每一个Key会绑定一个State,但是这在。很好理解,一个特定的Operator算子共享同一个state,这是实现层面很好做好的。一般来说,正常的人第一眼就会想到:一个task绑定一个。也就是描述符的名字有关的,这就是为什么描述符必须是唯一的,关于。是从每个record中获取的,所以在。方法中才会更新对应的Key值。是在哪里初始化的,可以看。

2023-06-23 18:58:06 1255

原创 Spark中python和jvm的通信杂谈--ArrowConverter

这个方法中,python调用spark中方法,把序列化的*Iterator[Array[Byte]]*传给jvm执行,具体的细节,读者可以自行参考源代码.直接内存,这样可以避免了JVM内存到native内存的数据拷贝,尤其是在大数据场景下,提升的效率更加明显,且减少了用户态和内核态的切换次数。这个项目,该项目的初衷是加速进程间的数据交换,从目前的社区发展以及它的周边来看,其实是一个很不错的项目。的方式,大大提升了进程间的数据交换效率。与spark jvm进行交互,而数据的交换采用的是。

2023-06-21 23:24:58 684

原创 Apache Hudi初探(一)(与flink的结合)

long ckpTimeout = * 获取到。的方式,只需要引入了对应的jar包即可,以。的方式,所以不需要像使用。的超时时间,并设置为。

2023-06-18 16:53:18 1422 1

原创 Apache Hudi初探(九)(与spark的结合)--非bulk_insert模式

来说,什么也不操作(因为该index每次都会从parquet文件中读取信息从而组装成index),构建一个状态信息,主要是记录一下插入的记录数量和更新的记录数量 其中主要形成了以。(默认是true)会进行元数据的commit操作,这些commit的操作和之前。,则会要求排序,如果没有则只是按照partitioner进行重分区,(这里暂时忽略),主要是对数据进行分区处理,设计到小文件的处理。操作,所以没有去重的需要,所以直接采用spark原生的方式,实例的构造方法中会进行一些额外的操作。

2023-06-10 06:17:02 1193

原创 Apache Hudi初探(八)(与spark的结合)--非bulk_insert模式

并且从*.hoodie/20230530073115535.deltacommit* 获取internalSchemaOpt,具体的合并就是把即将写入的schema和internalSchemaOpt进行合并。因为是"bulk insert"操作,所以没有去重的需要,所以直接采用spark原生的方式,把df的schema转换成avro的schema。),则会进行去重处理,具体是调用。开始写操作,这涉及到回滚的操作。,就会进行schema的合并。是没有的,所以不会开启异步的。

2023-06-01 07:22:07 662

原创 Apache Hudi初探(七)(与spark的结合)

目前hudi的与spark的集合还是基于spark datasource V1来的,这一点可以查看。最后还会在spark中刷新刚才建立的表,这样才spark的查询中就能查询到插入的hudi表。为true(默认是false,不开启),于此同时会把。表,分别对应snapshot表(实时表)和读优化表。这里主要是同步到数据到hive的元数据中,如果。),则读优化表,则不会家*_ro*后缀。集合中,便于后续调用,当然如果设置了。表来说,会有两张表,一张是*_rt。开启(默认是false,不开启)

2023-05-21 23:54:54 522

原创 Apache Hudi初探(六)(与spark的结合)

目前hudi的与spark的集合还是基于spark datasource V1来的,这一点可以查看。之前说到只有获取到分布式锁的线程才可以继续一下操作。后续发现也是基于Datasource V2的。

2023-05-19 00:22:26 401

原创 Apache Hudi初探(五)(与spark的结合)

目前hudi的与spark的集合还是基于spark datasource V1来的,这一点可以查看。所以默认情况clean和Archive服务都不是异步后台服务。是否开启异步clean清理服务。是否开启archive归档服务。的实例,该实例的对一个的。

2023-05-15 22:58:31 568

spark调优案例分享

spark的调优案例分享

2023-11-13

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除