Kıvılcım, tek bir RDD'yi ikiye en iyi şekilde böler


10

Belirli parametrelere göre gruplara ayırmak için gereken büyük bir veri kümesi var. İşin mümkün olduğunca verimli bir şekilde işlenmesini istiyorum. Bunu yapmanın iki yolunu hayal edebilirim

Seçenek 1 - Orijinal RDD'den harita oluşturma ve filtreleme

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()

Seçenek 2 - Orijinal RDD'yi doğrudan filtreleyin

def customFilter(record):
    return passesSomeTest(record)

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

Yumruk yöntemi orijinal veri kümesinin tüm kayıtlarını 3 kez yinelemek zorundadır, burada ikincisi sadece iki kez yapmak zorundadır, ancak normal koşullar altında kıvılcım sahnelerin grafik binasının arkasında bazı şeyler yapar, bu yüzden etkili bir şekilde aynı şekilde yapılır. Sorularım: a.) Bir yöntem diğerinden daha verimli mi, yoksa kıvılcım grafiği oluşturma onları eşdeğer yapıyor mu?) Bu ayrımı tek bir geçişte yapmak mümkün mü


Kendimi de çok benzer bir problemle buldum ve gerçekten bir çözüm bulamadım. Ancak gerçekte olan bu koddan net değildir, çünkü kıvılcım 'tembel bir değerlendirmeye' sahiptir ve sözde sadece gerçekten yürütmesi gereken şeyi ve ayrıca haritaları, filtreleri ve birlikte yapılabilecekleri birleştirebilmektedir. Yani muhtemelen sen ne tarif edebilir tek geçişte olur. Bununla birlikte, tembel değerlendirme mekanizmalarını anlatacak kadar tanıdık değil. Aslında ben sadece .cache () fark ettim. Belki de sadece bir .cache () yapmanın ve sonuçların tamamını almanın bir yolu vardır?
user3780968

Yanıtlar:


9

Öncelikle size bir Spark uzmanı olmadığımı söyleyeyim; Son birkaç aydır çok kullanıyorum ve şimdi anladığımı düşünüyorum, ama yanlış olabilirim.

Sorularınızı cevaplamak için:

a.) eşdeğerdirler, ancak gördüğünüz şekilde değildir; Merak ediyorsanız Spark grafiği optimize etmeyecektir, ancak customMapperyine de her iki durumda da iki kez yürütülecektir; bunun sebebi kıvılcım için rdd1ve rdd2iki tamamen farklı RDD'dir ve yapraklardan başlayarak dönüşüm grafiğini aşağıdan yukarıya doğru inşa edecektir; böylece Seçenek 1 şu dile çevrilecektir:

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()

Söylediğiniz gibi customMapper, iki kez yürütülür (dahası, rddIniki kez de okunacaktır, yani bir veritabanından geliyorsa, daha da yavaş olabilir).

b.) bir yol var, sadece cache()doğru yere gitmelisin:

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

Bunu yaparak kıvılcımın kısmi sonuçlarını saklayabileceğini söylüyoruz mappedRdd; daha sonra bu kısmi sonuçları hem rdd1ve için kullanır rdd2. Kıvılcım açısından bu şuna eşittir:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.