Spark: 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 ครั้ง ถ้าฉันเพิ่ม "test3" จากคอลัมน์ "test.three" ดังนั้น UDF จะถูกดำเนินการอีกครั้ง

มีคนอธิบายได้ไหมทำไม

สามารถหลีกเลี่ยงสิ่งนี้ได้อย่างถูกต้องหรือไม่ (โดยไม่ต้องแคชข้อมูลหลังจากที่เพิ่ม "test" แม้ว่าจะใช้งานได้)?


คุณหมายถึงอะไร คุณกำลังเรียกใช้ฟังก์ชันทดสอบสามครั้ง นั่นเป็นเหตุผลที่มันถูกประหารชีวิตสามครั้ง ไม่แน่ใจว่าทำไมคุณถึงทำให้มันเป็น UDF ทำไมไม่ทำแผนที่เป็นวาล?
user4601931

นี่เป็นเพียงตัวอย่างเพื่อแสดงพฤติกรรมของประกายไฟ สำหรับฉัน "test" เป็นคอลัมน์ใหม่ที่มีโครงสร้างจากนั้นการเข้าถึงส่วนใด ๆ ของโครงสร้างไม่ควรเรียกใช้ UDF อีกครั้ง ฉันผิดหรือเปล่า?
Rolintocour

ฉันพยายามพิมพ์ schema, DataType ของ "test" คือMapไม่ใช่ Struct ตอนนี้แทนที่จะส่งคืนแผนที่ถ้า UDF ส่งคืนคลาสเคสเช่นการทดสอบ (หนึ่งสตริงสอง: สตริง) ดังนั้นtestแท้จริงแล้วเป็นโครงสร้าง แต่มีการประมวลผล UDF จำนวนมากเสมอ
Rolintocour

เกี่ยวข้อง: stackoverflow.com/questions/40320563/…
Raphael Roth

แคชควรทำงานตามคำตอบนี้: stackoverflow.com/a/40962714/1138523
Raphael Roth

คำตอบ:


5

หากคุณต้องการหลีกเลี่ยงการเรียกหลาย ๆ ครั้งไปที่ udf (ซึ่งมีประโยชน์โดยเฉพาะถ้า udf เป็นคอขวดในงานของคุณ) คุณสามารถทำได้ดังนี้:

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

โดยพื้นฐานแล้วคุณบอกว่า Spark ไม่ได้กำหนดฟังก์ชั่นของคุณและตอนนี้ Spark ทำให้แน่ใจว่าถูกเรียกเพียงครั้งเดียวเพราะมันไม่ปลอดภัยที่จะเรียกมันหลายครั้ง

นอกจากนี้โปรดทราบว่าเคล็ดลับนี้ไม่ได้ฟรีโดยการทำเช่นนี้คุณกำลังวางข้อ จำกัด บางอย่างไว้ในเครื่องมือเพิ่มประสิทธิภาพผลข้างเคียงอย่างหนึ่งของตัวอย่างนี้คือ Spark Optimizer ไม่ได้ผลักตัวกรองผ่านการแสดงออกที่ไม่ได้กำหนดไว้ดังนั้นคุณจึงต้องรับผิดชอบ ตำแหน่งของตัวกรองในแบบสอบถามของคุณ


ดี! คำตอบนี้ยังเป็นของที่นี่: stackoverflow.com/questions/40320563/…
Raphael Roth

ในกรณีของฉันasNondeterministicบังคับให้ UDF ดำเนินการเพียงครั้งเดียว ด้วยexplode(array(myUdf($"id")))วิธีการแก้ปัญหาก็ยังคงได้รับการดำเนินการสองครั้ง
Rolintocour
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.