สปาร์คแยก RDD เดี่ยวออกเป็นสองส่วนอย่างเหมาะสมที่สุด


10

ฉันมีชุดข้อมูลขนาดใหญ่ที่ฉันจำเป็นต้องแบ่งออกเป็นกลุ่มตามพารามิเตอร์เฉพาะ ฉันต้องการให้งานดำเนินการอย่างมีประสิทธิภาพมากที่สุด ฉันจินตนาการได้สองวิธี

ตัวเลือกที่ 1 - สร้างแผนที่จาก RDD ดั้งเดิมและตัวกรอง

def customMapper(record):
    if passesSomeTest(record):
        return (1,record)
    else:
        return (0,record)

mappedRdd = rddIn.map(lambda x: customMapper(x))
rdd0 = mappedRdd.filter(lambda x: x[0]==0).cache()
rdd1 = mappedRdd.filter(lambda x: x[1]==1).cache()

ตัวเลือก 2 - กรอง RDD ดั้งเดิมโดยตรง

def customFilter(record):
    return passesSomeTest(record)

rdd0 = rddIn.filter(lambda x: customFilter(x)==False).cache()
rdd1 = rddIn.filter(customFilter).cache()

วิธีการกำปั้นต้องวนซ้ำไปตามระเบียนทั้งหมดของชุดข้อมูลเดิม 3 ครั้งโดยครั้งที่สองจะต้องทำสองครั้งภายใต้สถานการณ์ปกติอย่างไรก็ตามประกายไฟบางอย่างอยู่เบื้องหลังการสร้างกราฟฉากดังนั้นฉันสามารถจินตนาการได้ว่าพวกเขาเป็น ทำได้อย่างมีประสิทธิภาพในลักษณะเดียวกัน คำถามของฉันคือ: a.) เป็นวิธีหนึ่งที่มีประสิทธิภาพมากกว่าวิธีอื่นหรือไม่หรือการสร้างกราฟประกายทำให้เทียบเท่า b.) เป็นไปได้หรือไม่ที่จะทำแยกนี้ในครั้งเดียว


ฉันพบว่าตัวเองมีปัญหาที่คล้ายกันมากและไม่พบวิธีแก้ปัญหา แต่สิ่งที่เกิดขึ้นจริงนั้นไม่ชัดเจนจากโค้ดนี้เนื่องจาก spark มี 'การประเมินแบบสันหลังยาว' และคาดว่าจะสามารถดำเนินการเฉพาะสิ่งที่จำเป็นในการดำเนินการและการรวมแผนที่ตัวกรองและสิ่งที่สามารถทำร่วมกัน ดังนั้นสิ่งที่คุณอาจอธิบายอาจเกิดขึ้นในครั้งเดียว ไม่คุ้นเคยเพียงพอกับกลไกการประเมินผลที่ขี้เกียจที่จะบอก ที่จริงฉันเพิ่งสังเกตเห็น. cache () อาจเป็นวิธีเดียวในการทำ. cache () และรับผลลัพธ์ทั้งหมดหรือไม่
user3780968

คำตอบ:


9

ก่อนอื่นให้ฉันบอกคุณว่าฉันไม่ใช่ผู้เชี่ยวชาญประกายไฟ ฉันใช้มันบ่อยมากในช่วงสองสามเดือนที่ผ่านมาและฉันเชื่อว่าตอนนี้ฉันเข้าใจแล้ว แต่ฉันอาจผิด

ดังนั้นตอบคำถามของคุณ:

ก.) สิ่งเหล่านี้เทียบเท่ากัน แต่ไม่ใช่ในแบบที่คุณเห็น Spark จะไม่ปรับกราฟให้เหมาะสมหากคุณสงสัย แต่customMapperจะยังคงทำงานสองครั้งในทั้งสองกรณี นี่เป็นเพราะความจริงที่ว่าสำหรับประกายไฟrdd1และrdd2เป็น RDD สองแบบที่แตกต่างอย่างสิ้นเชิงและมันจะสร้างกราฟการแปลงจากล่างขึ้นบนเริ่มจากใบไม้ ดังนั้นตัวเลือก 1 จะแปลเป็น:

rdd0 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==0).cache()
rdd1 = rddIn.map(lambda x: customMapper(x)).filter(lambda x: x[0]==1).cache()

ดังที่คุณกล่าวว่าcustomMapperจะทำงานสองครั้ง (ยิ่งไปกว่านั้นrddInจะสามารถอ่านได้สองครั้งซึ่งหมายความว่าหากมาจากฐานข้อมูลอาจช้าลง)

b.) มีวิธีคุณต้องไปcache()ถูกที่แล้ว:

mappedRdd = rddIn.map(lambda x: customMapper(x)).cache()
rdd0 = mappedRdd.filter(lambda x: x[0]==0)
rdd1 = mappedRdd.filter(lambda x: x[0]==1)

โดยการทำเช่นนี้เรากำลังบอกว่ามันสามารถเก็บผลลัพธ์บางส่วนของmappedRdd; ก็จะใช้ผลเหล่านี้บางส่วนทั้งในและrdd1 rdd2จากจุดประกายของมุมมองนี้เทียบเท่ากับ:

mappedRdd = rddIn.map(lambda x: customMapper(x)).saveAsObjectFile('..')
# forget about everything
rdd0 = sc.objectFile('..').filter(lambda x: x[0]==0)
rdd1 = sc.objectFile('..').filter(lambda x: x[0]==1)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.