Spark은 개발자가 만든 코드를 어떻게 변환하여 실행하는가?
- 다음 데이터 프레임 연산을 자세히 보자
spark.read.option("header", True).csv("test.csv"). \
where("gender" <> "F"). \
select("name", "gender"). \
groupby("gender"). \
count(). \
show()
- WHERE, SELECT는 셔플링 없이 파티션에서 독립적으로 작업을 수행할 수 있다.
- 그런데 GROUPBY가 호출되는 순간 GROUPBY 키에 맞게, 같은 값을 갖는 레코드들이 같은 파티션으로 재정렬이 되어야하기 때문에, 셔플링이 발생한다.
- COUNT 자체는 해당 파티션에서 병렬적으로 작업이 가능하다.
- SHOW는 일부 레코드를 DRIVER로 가져온다.
- ACTION
- ACTION 작업이 수행될 때, 그 앞에 연산이 수행된다(SHOW가 대표적인 ACTION)
- 데이터프레임을 READ 하는 것도 작업에 따라서 ACTION이 될 수 있다.
- 기본적으로 SPARK DATAFRAME의 OPERATION들은 ACTION이 발생하기 전까지는 실행이 안되는 LAZY EXECUTION을 따라가고 있다.
- READ, WRITE, SHOW, COLLECT -> JOB을 실행시킴(실제 코드가 실행됨)
- LAZY EXECUTION
- 어떤 장점이 존재할까?
- 더 많은 오퍼레이션을 볼 수 있기에 최적화를 잘 할 수 있음. 그래서 SQL이 선호됨
- 어떤 장점이 존재할까?
- ACTION은 JOB이라고도 한다. 결국 내가 작성하는 SPARK 코드는 하나 혹은 그 이상의 JOB으로 구성되며, 하나의 JOB은 다수의 TRANSFORMATION으로 구성되며
- 이 TRANSFORMATION이 NARROW냐 WIDE에 따라서 STAGE로 구성된다.
- 한 STAGE : 셔플링 없이 독립적으로, 병렬적으로 가능한 연산으로 구성
- 내 JOB에서 셔플링이 생기면 STAGE가 하나 더 생김
- TRANSFORMATION
- NARROW DEPENDENCIES TRANSFORMATION : PARTITION 안에서 병렬적으로 가능한 처리
- SELECT, FILTER, MAP 등등
- WIDE DEPENDENCIES TRANSFORMATION : PARTITION 간 셔플링이 필요한 처리
- GROUPBY, REDUCEBY, PARTITIONBY, REPARTITION, COALESCE 등등
- NARROW DEPENDENCIES TRANSFORMATION : PARTITION 안에서 병렬적으로 가능한 처리
- Stage 1 : WHERE, SELECT
- GROUPBY
- Stage 2 : COUNT, SHOW
Jobs, Stages, Tasks
- Action -> Job -> 1 + Stages -> 1 + Tasks
- Action
- Job을 하나 만들어내고 코드가 실제로 실행됨
- Job
- 하나 혹은 그 이상의 Stage로 구성됨
- Stage는 Shuffling이 발생하는 경우 새로 생김
- Stage
- Dag의 형태로 구성된 Task들 존재
- 여기 Task들은 병렬 실행이 가능
- Task
- 가장 작은 실행 유닛으로 Executor에 의해 실행됨
spark.read.option("header", True). \
csv("test.csv"). \
where("gender <> 'F'"). \
select("name", "gender"). \
groupby("gender"). \
cont(). \
show()
- option("inferSchema, True)가 추가 되면 JOB이 하나 더 추가됨
- read를 통해, header가 True기 때문에 첫번째 row를 읽어야해서, Job 0 추가
- Job1은 Groupby가 있기 때문에, 두개의 stage로 구성된다.
- where, select 에 의해 narrow dependency transformation
- Exchange는 셔플링을 의미 : gender의 값에 맞춰 파티션이 새로 만들어져야한다.
- Job1의 마지막은 show에 의해서 Trigger, collect limit이라고 작게 있는데 20개의 레코드를 collect해서 드라이버 쪽으로 보낸다.
- 웹 UI를 통해서 확인하면서, 어디가 Bottle neck인지 등 확인할 수 있다.
'데이터 엔지니어링 > Spark' 카테고리의 다른 글
26. Spark 내부 동작(Bucketing과 Partitioning) (0) | 2023.08.23 |
---|---|
25. Spark 내부 동작(Execution Plan 실습, Spark Web UI) (0) | 2023.08.22 |
23. Spark 내부 동작(Spark 파일 포맷, Partition 저장 형태, Schema가 있는 데이터의 Merge) (0) | 2023.08.22 |
22. Unit Test (0) | 2023.08.22 |
21. Hive 메타스토어 사용하기 (0) | 2023.08.22 |