2017-12-22 138 views
7

tôi chạy vào một hành vi đáng ngạc nhiên khi sử dụng .select():Chính xác là gì .select() làm gì?

>>> my_df.show() 
+---+---+---+ 
| a| b| c| 
+---+---+---+ 
| 1| 3| 5| 
| 2| 4| 6| 
+---+---+---+ 

>>> a_c = s_df.select(col("a"), col("c")) # removing column b 
>>> a_c.show() 
+---+---+ 
| a| c| 
+---+---+ 
| 1| 5| 
| 2| 6| 
+---+---+ 

>>> a_c.filter(col("b") == 3).show() # I can still filter on "b"! 
+---+---+ 
| a| c| 
+---+---+ 
| 1| 5| 
+---+---+ 

Hành vi này có tôi tự hỏi ... Có điểm sau đây của tôi có đúng không?

DataFrames chỉ là chế độ xem, một DataFrame đơn giản là chế độ xem của chính nó. Trong trường hợp của tôi a_c chỉ là một cái nhìn vào my_df.

Khi tôi tạo a_c không có dữ liệu mới được tạo, a_c chỉ trỏ vào cùng một dữ liệu my_df đang trỏ.

Nếu có thêm thông tin có liên quan, vui lòng thêm!

Trả lời

6

Điều này đang xảy ra do bản chất của Spark. Đó là "thông minh", đủ để đẩy bộ lọc xuống để nó xảy ra ở mức thấp hơn - trước bộ lọc *. Vì vậy, vì tất cả điều này xảy ra trong cùng một stage thực thi và vẫn có thể được giải quyết. Trong thực tế, bạn có thể thấy điều này trong explain:

== Physical Plan == 
*Project [a#0, c#2] 
+- *Filter (b#1 = 3) <---Filter before Project 
    +- LocalTableScan [A#0, B#1, C#2] 

Bạn có thể buộc một shuffle và giai đoạn mới, sau đó xem bộ lọc của bạn thất bại, mặc dù. Thậm chí bắt nó ở thời gian biên dịch. Dưới đây là ví dụ:

a_c.groupBy("a","c").count.filter(col("b") === 3) 

* Cũng có một phép cắt tỉa sẽ đẩy lựa chọn xuống lớp cơ sở dữ liệu nếu nó nhận ra nó không cần cột bất kỳ lúc nào. Tuy nhiên tôi tin rằng bộ lọc sẽ làm cho nó "cần" nó và không tỉa ... nhưng tôi đã không kiểm tra điều đó.

1

Hãy để chúng tôi bắt đầu với một số khái niệm cơ bản về tia lửa tiềm ẩn. Điều này sẽ giúp bạn hiểu dễ dàng. RDD: Nằm dưới lõi tia lửa là cấu trúc dữ liệu được gọi là RDD, được đánh giá một cách lười biếng là . Bằng cách đánh giá lười biếng, chúng tôi có nghĩa là tính toán RDD xảy ra khi hành động (như gọi số đếm trong RDD hoặc hiển thị trong tập dữ liệu).

Tập dữ liệu hoặc Dataframe (trong đó Tập dữ liệu [Row]) cũng sử dụng RDD ở lõi.

Điều này có nghĩa là mọi phép chuyển đổi (như bộ lọc) sẽ chỉ được thực hiện khi hành động được kích hoạt (hiển thị).

Vì vậy, câu hỏi của bạn "Khi tôi tạo a_c không có dữ liệu mới được tạo, a_c chỉ trỏ vào cùng một dữ liệu my_df đang trỏ."
Vì không có dữ liệu nào được nhận ra. Chúng ta phải nhận ra nó để đưa nó vào trí nhớ. Bộ lọc của bạn hoạt động trên khung dữ liệu ban đầu. Cách duy nhất để làm cho a_c.filter(col("b") == 3).show() ném ngoại lệ thời gian chạy của bạn là lưu vào bộ đệm dữ liệu trung gian của bạn bằng cách sử dụng dataframe.cache. Vì vậy, tia lửa sẽ ném "chính" org.apache.spark.sql.AnalysisException: Không thể giải quyết tên cột Ví dụ:

val a_c = s_df.select(col("a"), col("c")).cache 
     a_c.filter(col("b") == 3).show() 

Vì vậy, tia lửa sẽ ném "chính" org.apache.spark.sql.AnalysisException: Can tên cột không quyết tâm.

+0

cập nhật câu trả lời theo đề nghị của @ Chris H –

+0

Tôi nghĩ mà không giải thích giai đoạn giải thích này thiếu thịt của những gì đang xảy ra thực sự –

+0

@ JustinPihony- Tôi nghĩ giai đoạn không đủ logic trong trường hợp này. –