ฉันคิดว่าคำถามจะเป็นสูตรที่ดีกว่าเป็น:
เมื่อใดที่เราต้องเรียกแคชหรือคงอยู่บน RDD?
กระบวนการของ Spark นั้นขี้เกียจนั่นคือจะไม่มีอะไรเกิดขึ้นจนกว่าจะจำเป็น หากต้องการตอบคำถามอย่างรวดเร็วหลังจากval textFile = sc.textFile("/user/emp.txt")
ออกแล้วจะไม่มีสิ่งใดเกิดขึ้นกับข้อมูลเพียงอย่างเดียวที่HadoopRDD
สร้างขึ้นโดยใช้ไฟล์เป็นแหล่งข้อมูล
สมมติว่าเราแปลงข้อมูลนั้นเล็กน้อย:
val wordsRDD = textFile.flatMap(line => line.split("\\W"))
อีกครั้งไม่มีอะไรเกิดขึ้นกับข้อมูล ขณะนี้มี RDD ใหม่wordsRDD
ที่มีการอ้างอิงถึงtestFile
และฟังก์ชั่นที่จะใช้เมื่อจำเป็น
เฉพาะเมื่อมีการเรียกการกระทำจาก RDD เช่นเดียวwordsRDD.count
กับห่วงโซ่ RDD ที่เรียกว่าเชื้อสายจะถูกดำเนินการ นั่นคือข้อมูลถูกแบ่งย่อยในพาร์ติชันจะถูกโหลดโดยตัวจัดการของคลัสเตอร์ Spark flatMap
ฟังก์ชันจะถูกนำไปใช้และผลลัพธ์จะถูกคำนวณ
บนสายเลือดเชิงเส้นเช่นเดียวกับในตัวอย่างcache()
นี้ไม่จำเป็น ข้อมูลจะถูกโหลดไปยังตัวจัดการการแปลงทั้งหมดจะถูกนำไปใช้และในที่สุดก็count
จะถูกคำนวณทั้งหมดในหน่วยความจำ - ถ้าข้อมูลพอดีกับหน่วยความจำ
cache
มีประโยชน์เมื่อสายเลือดของ RDD แตกแขนงออกไป สมมติว่าคุณต้องการกรองคำของตัวอย่างก่อนหน้านี้เป็นจำนวนสำหรับคำบวกและลบ คุณสามารถทำสิ่งนี้ได้:
val positiveWordsCount = wordsRDD.filter(word => isPositive(word)).count()
val negativeWordsCount = wordsRDD.filter(word => isNegative(word)).count()
ที่นี่แต่ละสาขามีการโหลดข้อมูลใหม่ การเพิ่มcache
คำสั่งที่ชัดเจนจะทำให้มั่นใจได้ว่าการประมวลผลที่ทำไว้ก่อนหน้านี้ได้รับการเก็บรักษาและนำกลับมาใช้ งานจะมีลักษณะเช่นนี้:
val textFile = sc.textFile("/user/emp.txt")
val wordsRDD = textFile.flatMap(line => line.split("\\W"))
wordsRDD.cache()
val positiveWordsCount = wordsRDD.filter(word => isPositive(word)).count()
val negativeWordsCount = wordsRDD.filter(word => isNegative(word)).count()
ด้วยเหตุผลcache
ดังกล่าวจึงได้รับการกล่าวขานว่า 'ทำลายเชื้อสาย' เนื่องจากสร้างจุดตรวจสอบที่สามารถนำมาใช้ซ้ำเพื่อการประมวลผลต่อไป
Rule of thumb: ใช้cache
เมื่อเชื้อสายของ RDD ของคุณแตกแขนงออกหรือเมื่อใช้ RDD หลายครั้งเหมือนในลูป