Spark, tối ưu tách một RDD thành hai


10

Tôi có một bộ dữ liệu lớn mà tôi cần chia thành các nhóm theo các thông số cụ thể. Tôi muốn công việc xử lý hiệu quả nhất có thể. Tôi có thể hình dung hai cách làm như vậy

Tùy chọn 1 - Tạo bản đồ từ RDD ban đầu và bộ lọc

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

Tùy chọn 2 - Lọc trực tiếp RDD gốc

def customFilter(record):
    return passesSomeTest(record)

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

Phương pháp nắm tay phải lặp đi lặp lại trên tất cả các bản ghi của dữ liệu gốc được đặt 3 lần, trong đó lần thứ hai chỉ phải thực hiện hai lần, trong trường hợp bình thường, tuy nhiên, tia lửa tạo ra một số hình ảnh phía sau cảnh, vì vậy tôi có thể tưởng tượng rằng chúng là thực hiện hiệu quả theo cách tương tự. Câu hỏi của tôi là: a.) Là một phương pháp hiệu quả hơn phương pháp kia, hay việc xây dựng biểu đồ tia lửa làm cho chúng tương đương b.) Có thể thực hiện việc phân tách này trong một lần duy nhất


Tôi cũng tìm thấy bản thân mình với một vấn đề rất giống nhau và không thực sự tìm ra giải pháp. Nhưng những gì thực sự xảy ra không rõ ràng từ mã này, bởi vì Spark có 'đánh giá lười biếng' và được cho là chỉ có khả năng thực thi những gì nó thực sự cần thực hiện, và cả kết hợp bản đồ, bộ lọc và bất cứ điều gì có thể được thực hiện cùng nhau. Vì vậy, có thể những gì bạn mô tả có thể xảy ra trong một lần duy nhất. Không đủ quen thuộc với các cơ chế đánh giá lười biếng để nói, mặc dù. Thật ra tôi chỉ chú ý đến .cache (). Có lẽ có một cách chỉ làm một .cache () và nhận được kết quả đầy đủ?
dùng3780968

Câu trả lời:


9

Trước hết hãy để tôi nói với bạn rằng tôi không phải là chuyên gia về Spark; Tôi đã sử dụng nó khá nhiều trong vài tháng qua và tôi tin rằng bây giờ tôi đã hiểu nó, nhưng tôi có thể sai.

Vì vậy, trả lời câu hỏi của bạn:

a.) chúng tương đương nhau, nhưng không phải theo cách bạn nhìn thấy nó; Spark sẽ không tối ưu hóa biểu đồ nếu bạn đang tự hỏi, nhưng customMappernó vẫn sẽ được thực hiện hai lần trong cả hai trường hợp; điều này là do thực tế là đối với tia lửa rdd1rdd2là hai RDD hoàn toàn khác nhau và nó sẽ xây dựng biểu đồ biến đổi từ dưới lên bắt đầu từ các lá; vì vậy, lựa chọn 1 sẽ dịch sang:

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

Như bạn đã nói, customMapperđược thực hiện hai lần (hơn nữa, cũng rddInsẽ được đọc hai lần, điều đó có nghĩa là nếu nó đến từ cơ sở dữ liệu, nó có thể còn chậm hơn).

b.) có một cách, bạn chỉ cần di chuyển cache()đúng nơi:

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

Bằng cách này, chúng tôi đang nói với tia lửa rằng nó có thể lưu trữ kết quả một phần của mappedRdd; sau đó nó sẽ sử dụng các kết quả một phần này cho cả rdd1rdd2. Từ quan điểm tia lửa, điều này tương đương với:

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.