Scala主键引号校验从collect-map-foreach改Spark/SQL函数的优化咨询
问题解答
1. 改写后的函数是否综合表现更优
是的,改写后的版本综合表现远好于最初的版本,小数据量下性能接近是因为100条数据的规模太小,分布式计算的收益被任务调度开销抵消,当数据量达到十万级及以上时差距会非常显著:
- 原始实现会把整个主键列的所有数据全部拉取到Driver节点做单节点计算,数据量稍大就会导致Driver内存溢出,且完全浪费了集群的分布式算力。
- 改写后的实现将判断逻辑下发到所有Executor并行执行,仅会将命中规则的结果返回Driver,无论是内存开销还是计算效率都优于原始版本。
2. 可优化的空间
你可以从以下几个方向进一步优化:
- 优先使用Spark内置函数替代自定义UDF:自定义UDF会有额外的序列化、反序列化开销,Spark原生的字符串函数经过了专项优化,性能更高。你可以直接用
rlike正则匹配单双引号,无需自定义UDF。 - 提前终止全表扫描:无需收集所有命中引号的结果,只要判断是否存在符合规则的数据即可,加上
limit(1)后只要扫描到第一条符合条件的数据就会终止任务,无需遍历全表,数据量越大收益越高。 - 增加空值过滤:避免主键列存在null值时调用字符串方法抛出空指针异常。
优化后的代码示例
import org.apache.spark.sql.functions.col def checkForQuotesInPrimaryKeyColumnsOptimized(primaryKey: String, records: DataFrame): Boolean = { records .filter(col(primaryKey).isNotNull) .select(primaryKey) .filter(col(primaryKey).rlike("[\"']")) .limit(1) .collect() .nonEmpty }
如果需要打印命中引号的具体值,可在limit(1)前加一行.take(1).foreach(v => println("Value that has quotes: " + v(0).toString))即可。
内容的提问来源于stack exchange,提问作者Waltz
相关产品推荐
相关产品推荐

