51、Spark性能优化之优化数据结构

本文探讨了通过优化数据结构来降低内存使用的方法,包括优先使用数组和字符串而非集合类,避免多层嵌套对象,以及用int替代String。这些策略有助于减少内存开销,提高应用程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

优化数据结构

要减少内存的消耗,除了使用高效的序列化类库以外,还有一个很重要的事情,就是优化数据结构。从而避免Java语法特性中所导致的额外内存的开销,比如基于指针的Java数据结构,以及包装类型。
有一个关键的问题,就是优化什么数据结构?其实主要就是优化你的算子函数,内部使用到的局部数据,或者是算子函数外部的数据。都可以进行数据结构的优化。优化之后,都会减少其对内存的消耗和占用。

如何优化数据结构

1、优先使用数组以及字符串,而不是集合类
也就是说,优先用array,而不是ArrayList、LinkedList、HashMap等集合。
比如,有个List<Integer> list = new ArrayList<Integer>(),将其替换为int[] arr = new int[]。这样的话,array既比List少了额外信息的存储开销,还能使用原始数据类型(int)来存储数据,比List中用Integer这种包装类型存储数据,要节省内存的多。
还比如,通常企业级应用中的做法是,对于HashMap、List这种数据,统一用String拼接成特殊格式的字符串,比如Map<Integer, Person> persons = new HashMap<Integer, Person>()。可以优化为,特殊的字符串格式:id:name,address|id:name,address...。
2、避免使用多层嵌套的对象结构。
比如说,public class Teacher { private List<Student> students = new ArrayList<Student>() }。就是非常不好的例子。因为Teacher类的内部又嵌套了大量的小Student对象。
比如说,对于上述例子,也完全可以使用特殊的字符串来进行数据的存储。比如,用json字符串来存储数据,就是一个很好的选择。
{"teacherId": 1, "teacherName": "leo", students:[{"studentId": 1, "studentName": "tom"},{"studentId":2, "studentName":"marry"}]}
3、对于有些能够避免的场景,尽量使用int替代String。
因为String虽然比ArrayList、HashMap等数据结构高效多了,占用内存量少多了,但是之前分析过,还是有额外信息的消耗。比如之前用String表示id,那么现在完全可以用数字类型的int,来进行替代。
这里提醒,在spark应用中,id就不要用常用的uuid了,因为无法转成int,就用自增的int类型的id即可

1.集群的CDH版本为6.3.2,内置spark引擎版本约为spark2.4.0,目前hive默认的查询引擎为mr,且可供查询时临时切换的引擎只有spark; 3.该集群有3台namenode、51台datanode节点,单台namenode配置:64C256G16T,单台datanode配置:64C512G96T; 4.在运行以上sql任务时,集群同时还运行其他任务,期间Yarn内存总使用率约为50%,Yarn内核总使用率约为60%。 5.hive sql脚本(已优化)如下: -- 基础优化 SET hive.optimize.ppd=true; SET hive.execution.engine=spark; SET spark.master=yarn; SET spark.submit.deployMode=cluster; -- 资源分配(根据集群调整) -- 动态分配方案 SET spark.dynamicAllocation.enabled=true; SET spark.dynamicAllocation.minExecutors=25; SET spark.dynamicAllocation.maxExecutors=70; SET spark.dynamicAllocation.executorIdleTimeout=60s; SET spark.dynamicAllocation.schedulerBacklogTimeout=30s; -- 资源分配设置 SET spark.executor.memory=16g; SET spark.executor.cores=8; SET spark.driver.memory=10g; SET spark.yarn.executor.memoryOverhead=6g; -- 堆外内存(关键防OOM),提升shuffle安全边际 -- 性能优化参数 SET spark.sql.adaptive.enabled=true; -- 启用AQE,自适应优化执行计划 SET spark.sql.adaptive.coalescePartitions.enabled=true; SET spark.sql.adaptive.advisoryPartitionSizeInBytes=256000000; -- 256MB SET spark.sql.adaptive.shuffle.targetPostShuffleInputSize=268435456; -- 256MB SET spark.speculation=true; SET spark.sql.parquet.enableVectorizedReader=true; -- 加速Parquet -- 倾斜优化 SET spark.sql.adaptive.skewedJoin.enabled=true; -- 倾斜处理 SET spark.sql.adaptive.skewedPartitionFactor=3; SET spark.sql.adaptive.skewedPartitionThresholdInBytes=256MB; SET spark.sql.aggregate.ignoreInvalidSalt=true; --启用谓词下推 SET spark.sql.parquet.filterPushdown=true; -- Shuffle优化 SET spark.sql.shuffle.partitions=1500; SET spark.shuffle.file.buffer.size=1mb; SET spark.shuffle.compress=true; SET spark.shuffle.spill.compress=true; -- 内存与GC优化 SET spark.memory.fraction=0.8; SET spark.memory.storageFraction=0.5; SET spark.executor.extraJavaOptions=" -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=35 -XX:ConcGCThreads=8 -XX:G1HeapRegionSize=32m -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:G1MaxNewSizePercent=50"; -- Off-Heap内存优化 SET spark.memory.offHeap.enabled=true; SET spark.memory.offHeap.size=2g; -- 网络超时设置 SET spark.network.timeout=300s; SET spark.sql.broadcastTimeout=1800; -- 广播超时 -- 预计算日期参数(避免每行重复计算) SET hivevar:start_dt=regexp_replace(add_months('${etldate}',-3),'-',''); SET hivevar:end_dt=regexp_replace('${etldate}','-',''); SET hivevar:total_days=datediff('${etldate}',add_months('${etldate}',-3)); -- 创建新表 CREATE TABLE dws.B STORED AS PARQUET AS SELECT cust, SUM(nvl(bal, 0)) / ${total_days} AS avg_bal -- 使用预计算常量 FROM dwd.A WHERE dt <= '${end_dt}' AND dt > '${start_dt}' -- 直接使用预计算的分区值 AND cust IS NOT NULL AND cust <> '' AND ( -- 优化OR条件结构 (type_cd = 'D' AND stat_cd IN ('2','5','6')) OR (type_cd = 'W' AND stat_cd <> '4') OR (type_cd NOT IN ('D','W')) GROUP BY cust; 6.上述sql中表A分区字段为dt,格式为yyyyMMdd的字符串,表A为每日更新的全量数据,且数据量较大,单分区上亿,表A为parquet格式,参数etldate为跑批日期,格式为yyyy-MM-dd字符串; 对于以上hive sql脚本,假设表A数据不存在严重倾斜,但也不是十分均匀。现在我设置的运行参数如上所述,请为我详细分析: 以上参数设置是否合理? 参数间是否有冲突? 是否有多余的、可以省略设置的参数? 是否有遗漏未设置的参数? 以我的集群当前的运行情况和资源占用情况,以上参数对资源分配是否合理?
最新发布
07-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值