Transformation tạo DataFrame mới từ DataFrame cũ (filter, select, join, groupBy) và không chạy ngay — Spark chỉ ghi nó vào kế hoạch. Action (count, collect, show, write) mới buộc Spark thực thi toàn bộ chuỗi phía trước.
df = spark.read.parquet("s3://lake/orders/") # nothing is read yet
paid = df.filter(df.status == "PAID").select("user_id", "amount") # still lazy
paid.count() # action: the job runs hereVì sao lazy: thấy cả chuỗi trước khi chạy thì optimizer (Catalyst) mới tối ưu được.
- Predicate pushdown, column pruning — đẩy filter và select xuống lúc đọc Parquet, chỉ đọc cột và row group cần thiết.
- Gộp các bước narrow (filter → select → map) vào một stage, dữ liệu đi qua một lượt thay vì ghi tạm sau từng bước.
- Không tốn công tính những thứ cuối cùng không ai dùng.
Lưu ý: mỗi action chạy lại cả chuỗi từ nguồn. Gọi count() rồi write() trên cùng một DataFrame nặng là đọc nguồn hai lần; DataFrame dùng lại nhiều lần thì cache() hoặc persist(), dùng xong thì unpersist().