: MapReduce는 데이터 복제, 디스크 I/O, 직렬화로 인해 상당한 오버헤드가 발생함
-> Mapper M의 출력은 디스크에 저장되고 정렬된 후, 다시 Reducer R가 이를 읽음 (HDFS read, HDFS write)

=> MapReduce는 대규모 어플리케이션에 적합하게 잘 구성되지 않음. 여러 번의 map-reduce 단계를 연결해야 하는 경우가 많음
-> 데이터 흐름이 한 방향으로만 이루어진다면(DAG=Directed Acyclic Graph, 유향 비순환 그래프), 작업 단위로의 복구를 허용하여 전체 작업 대신 특정 작업을 복구할 수 O

: 표현력이 풍부한 컴퓨팅 시스템으로, MapReduce 모델에 국한되지 않음
<MapReduce모델에 대한 추가 사항>


-> General task graphs를 지원
-> 한 방향으로만 갈 수 있음(돌아갈 수 없음)
-> 단순한 순차적 작업만이 아니라, 더 복잡한 작업 흐름(병렬 수행 등) 구성 가능
-> Spark 같은 시스템에서는 단순한 Map-Reduce 형태가 아닌, 필터링, 집계, 조인 등 다양한 작업들이 여러 단계로 연결된 작업 그래프로 표현되며, 이를 통해 복잡한 데이터 처리 흐름을 쉽게 구현할 수 있음
: 오픈 소스 소프트웨어 (Apache Foundation에서 개발)
: Java, Scala, Python을 지원



-> RDD는 변경할 수 없음. Read-Only
-> 변경 대신 이전 RDD를 기반으로 새로운 RDD를 만들 수 있음
-> 그 이전 RDD에 대한 정보와 연산을 기록함(lineage)

< Spark RDD Operations > **** 둘의 차이
1) 변환(Transformations)
: 다른 RDD에 대한 결정론적 연산(동일입력에 대해 항상 동일결과 생성)을 통해 새로운 RDD를 생성하는 연산
-> Transformations의 예시: map, filter, join, union, intersection, distinct
-> Lazy evaluation: 변환은 즉시 실행되지 않고, 나중에 액션이 호출될 때까지 계산을 미룸. 성능을 최적화하고 불필요한 계산을 방지하기 위한 기법2) 액션(Action)
: 변환된 RDD의 데이터를 실제로 계산하고, 그 결과를 반환하거나 외부 시스템으로 내보냄(return, export data)
-> 즉시 평가, force calculation: 액션이 호출되면 Spark는 모든 지연된 반환들을 실행하여 최종 결과를 계산함
-> 액션의 예시: count, collect, reduce, save
-> 액션은 RDD에 적용될 수 있으며, 액션은 계산을 강제하고 값을 반환함
: RDD와 달리, 데이터가 이름이 지정된 열로 구성됨, 예를 들어 관계형 데이터베이스의 테이블과 유사
: 분산된 데이터 컬렉션에 구조를 부여하여 상위 수준 추상화를 제공
: DataFrame API의 확장판으로, 타입 안전(type-safe)하고 객체 지향적인 프로그래밍 인터페이스(object-oriented programming interface)를 제공(컴파일 시 오류 감지)
-> 두 API 모두 Spark SQL 엔진 위에서 구축되었으며, 둘 다 RDD로 변환 가능
-> Spark RDD를 확장하여 그래프 추상화를 제공: 각 vertex와 edge에 속성을 부여한 directed multigraph
성능 : Spark가 일반적으로 더 빠르지만 몇가지 제한 있음
-> Spark는 데이터를 메모리에서 처리할 수 O, but Hadoop MapReduce는 Map이나 Reduce 작업 후 데이터를 디스크에 저장함
-> Spark는 일반적으로 MapReduce보다 성능이 우수, but 좋은 성능을 위해서 많은 메모리 필요. 다른 리소스 요구 서비스가 있거나 메모리에 데이터를 모두 저장할 수 없는 경우 Spark의 성능이 저하됨
-> MapReduce는 다른 서비스들과 쉽게 함께 실행할 수 O, 설계된 1회성 작업에서는 성능 차이가 적음
사용 용이성: Spark는 더 높은 수준의 API를 제공하여 프로그래밍이 더 쉬움
데이터 처리: Spark는 더 일반적인 데이터 처리를 지원

<다른 예시>

-> 두 개의 관계형 테이블 R(A, B)와 S(B, C)가 각각 지정된 파일에 있음
-> 이 두 테이블에서 공통된 열 B를 기준으로 natural join을 해야함
-> 결과는 새로운 튜플 (A, B, C)를 생성하는 것
-> 해시 함수의 역할은 각 키를 기반으로 데이터를 적절한 Reduce 작업으로 보내는 것
Map 프로세스:
-> 입력 튜플 R(a,b)를 key-value pairs (b, (a, R))으로 변환
-> 입력 튜플 S(b,c)를 (b, (c, S))로 변환
Map 프로세스는 key b와 함께 각 key-value pairs를 Reduce 프로세스 h(b)로 전송
-> Hadoop은 이를 자동으로 처리하므로, k값만 지정하면 됨.
- MapReduce가 적합한 경우:
-> 순차적인 데이터 접근이 필요한 문제
-> 대규모 배치 작업(인터랙티브 or 실시간 아님)
- MapReduce가 비효율적인 경우: 데이터에 대한 랜덤(불규칙한) 접근이 필요한 문제
-> 그래프, 상호 의존적인 데이터( 머신러닝, 여러 항목 쌍을 비교하는 작업)