Hive & SparkSQL使用不同点
- hive中对空格、制表符、大小写的不明感,spark-sql中敏感(通过压缩sql,去掉敏感符号;字段大小写要匹配)
- 在shell中提交hive -e 和spark-sql -e,spark-sql需要用""显式的把字符串引起来
- spark-sql -e 执行时转义符号需要修改为[],而不可以使用//
SparkSQL优化(Spark2.x)
现在网上的一些调优方式很大一部分在spark2.x已经自动调优
- spark-sql命令只有本地driver client模式没有custer模式
参数调优
- 增大executor-memory内存,个数不要太多 (如果资源充足,增大内存能减少很多的异常)
- 控制executor-cores个数 (最好不要超过4个)
- spark.sql.shuffle.partitions=7000 (增大数shuffe时的并行度,依据依赖stage前后数量来设定)
spark.yarn.executor.memoryOverhead 值为executorMemory * 0.07, with minimum of 384 (通常不够用,暂设为1024,需要再增加
spark.sql.windowExec.buffer.spill.threshold=3000000 (默认值为
4096,调优窗口函数中用到)mapred.output.compress=true mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec (输出文件压缩为gzip,减少45%的存储空间)
spark.speculation=true (
开启spark的推测机制,开启推测机制后如果某一台机器的几个task特别慢,推测机制会将任务分配到其他机器执行,最后Spark会选取最快的作为最终结果)spark.reducer.maxReqsInFlight=512,spark.reducer.maxSizeInFlight=96m (优化
shuffle read time时间)- --conf spark.dynamicAllocation.enabled=true --conf spark.shuffle.service.enabled=true --conf spark.dynamicAllocation.executorIdleTimeout=60s --conf spark.dynamicAllocation.schedulerBacklogTimeout=10s --conf spark.dynamicAllocation.minExecutors=2 --conf spark.dynamicAllocation.maxExecutors=300 (设置动态资源分配,如果设置了`--num-executors`(或`spark.executor.instances`)并且大于此值,它将用作执行程序的初始数。)
spark.network.timeout=18000,默认为 120(120s),配置所有网络传输的延时,如果没有主动设置以下参数,默认覆盖其属性 spark.core.connection.ack.wait.timeout、spark.akka.timeout、spark.storage.blockManagerSlaveTimeoutMs、spark.shuffle.io.connectionTimeout、spark.rpc.askTimeout or spark.rpc.lookupTimeout
程序健壮性
- --conf spark.sql.shuffle.partitions=10000 --conf spark.sql.adaptive.enabled=true --conf spark.sql.adaptive.shuffle.targetPostShuffleInputSize=512000000 (尽可能多设置shuffle并行度,开起Adaptive Execution,设置合并度小文件阀值,实现自我调节)
实际操作的中的问题
执行速度问题
- 处理的文件数据量较大,存在shuffle。由于部分节点存在网络问题,导致计算时间严重倾斜(在yarn下线了有问题的机器)
小文件问题
失败的尝试(参数调整)
- --conf spark.default.parallelism=1000(无效,只适用于spak core,且文件可split)
- --conf spark.sql.adaptive.enabled=true --conf spark.sql.adaptive.shuffle.targetPostShuffleInputSize=128000000 (无效,这个配置是应用于读取小文件处理)
- --conf spark.sql.shuffle.partitions=1000 (无效,未发生shuffle;希望通过group by * 强制shuffle,但是字段中有Map类型…)
- set hive.merge.mapfiles=true;set mapred.max.split.size=256000000;set mapred.min.split.size.per.node=192000000;set mapred.min.split.size.per.rack=192000000;set hive.input.format="org.apache.hadoop.hive.ql.io.CombineHiveInputFormat";(无效,原因未排查,可能也是未shuffle)
失败的尝试(直接编写为spark core)
- repartition(有效,但10000->1000的shuffle时间已经超过了计算花费的时间,需要设置非常大的memoryOverhead)
- coalesce (无效,原因没有产生shuffle)
文件问题
- 文件为列式存储结构 parquet,利用spark2.x sql查询时抛异常 CorruptStatistics: Ignoring statistics because created_by could not be parsed (see PARQUET-251): parquet-mr (更改的配置文件$SPARK_HOME / conf / log4j.properties,log4j.logger.org.apache.parquet=ERROR)
参数问题
- 如果参数属性不是spark特有的属性,通过 --conf 配置无效,需要在hive中配置如:set hive.exec.compress.output=true;
序列化问题
- 设置 spark.serializer = org.apache.spark.serializer.KryoSerializer 对优化spark sql 没有效果(spark sql 数据集与RDD类似,但是,它们不使用Java序列化或Kryo,而是使用专用的编码器来序列化对象以便通过网络进行处理或传输。虽然编码器和标准序列化都负责将对象转换为字节,但编码器是动态生成的代码,并使用一种格式,允许Spark执行许多操作,如过滤,排序和散列,而无需将字节反序列化为对象)
导出查询结果
使用hive -e 或 spark-sql -e 在后面的SQL语句中如果有特殊符号需要转义,请使用 " [] "。不要使用 " \\ " 查询会出现问题,但在CLI中使用没有问题