스파크 : UDF가 여러 번 실행 됨


9

다음 코드가있는 데이터 프레임이 있습니다.

def test(lat: Double, lon: Double) = {
  println(s"testing ${lat / lon}")
  Map("one" -> "one", "two" -> "two")
}

val testUDF = udf(test _)

df.withColumn("test", testUDF(col("lat"), col("lon")))
  .withColumn("test1", col("test.one"))
  .withColumn("test2", col("test.two"))

이제 로그를 확인한 결과 각 행마다 UDF가 3 번 실행된다는 것을 알았습니다. "test.three"열에서 "test3"을 추가하면 UDF가 한 번 더 실행됩니다.

누군가 왜 나에게 설명 할 수 있습니까?

"테스트"가 추가 된 후 데이터 프레임을 캐싱하지 않아도 제대로 작동하지 않을 수 있습니까?


무슨 소리 야? 테스트 기능을 세 번 호출합니다. 그것이 세 번 실행되는 이유입니다. 왜 UDF로 만들고 있는지 잘 모르겠습니다. 왜지도를 발로 만들지 않습니까?
user4601931

이것은 스파크의 동작을 보여주는 예일뿐입니다. 나를 위해 "test"는 구조를 포함하는 새로운 열이며, 구조의 어떤 부분에 액세스해도 UDF를 다시 실행해서는 안됩니다. 내가 어떻게 틀렸어?
Rolintocour 2016

"test"의 DataType은 MapStruct 가 아니라 스키마를 인쇄하려고했습니다 . 이제 UDF가 Map (one String, two : String)과 같은 케이스 클래스를 리턴하면 맵을 리턴하는 대신 test실제로 Struct이지만 UDF 실행 횟수는 항상 있습니다.
Rolintocour 2016


캐싱은이 대답에 따라 작동합니다 : stackoverflow.com/a/40962714/1138523
라파엘 로스에게

답변:


5

udf에 대한 여러 호출을 피하려면 (특히 udf가 병목 현상이있는 경우에 유용합니다) 다음과 같이 수행 할 수 있습니다.

val testUDF = udf(test _).asNondeterministic()

기본적으로 Spark에게 함수가 결정적이지 않다고 말하면 이제 Spark는 여러 번 호출하는 것이 안전하지 않기 때문에 한 번만 호출되도록합니다 (각 호출마다 다른 결과를 반환 할 수 있음).

또한이 트릭은 무료가 아니라는 점에 유의하십시오.이 작업을 수행하면 옵티 마이저에 약간의 제약이 가해집니다. 이의 부작용 중 하나는 예를 들어 Spark 옵티마이 저가 결정적이지 않은 표현식을 통해 필터를 푸시하지 않으므로 최적의 책임을집니다. 검색어에서 필터의 위치


좋은! 이 답변은 여기에 있습니다 : stackoverflow.com/questions/40320563/…
Raphael Roth

필자의 경우 asNondeterministicUDF가 한 번만 실행되도록합니다. 으로 explode(array(myUdf($"id")))솔루션, 여전히 두 번 실행하세요.
Rolintocour
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.