스파크 : 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.