https://youtu.be/quzbmlYO7Rc?si=VmDoQ5gdQ-_V-EZp&t=2103

 

 

< 데이터 모델링이란 >

 

DB 사용자들이 필요로 하는 정보들을 도출하기 위해

최적의 자료 저장 구조가 되도록 데이터베이스, 테이블을 설계하는 기법

 

다르게 말하면, BI 팀에서 원하는 정보를 쉽고 빠르게 쿼리할 수 있도록

최적의 테이블 구조를 설계하는 것 (최적의 테이블 관계를 구축해두고, 데이터 IO 도 빠르게 할 수 있도록 설정해두고)

 

 

데이터의 논리적인 모델링을 진행하기 위해 아래 개념을 사용

- Entity(개체) : 테이블. ex) 학과 테이블, 학생 테이블

- Relationship : 테이블 간 관계. ex) 학생이 듣는 과목 코드(FK)-학과 코드(PK)

- Attribute : 테이블의 스키마. ex) 학생 테이블에는 학번, 이름, 주소, 성별, 전공 등 (key 값을 포함)

- Identifier : 테이블의 key.

 

위 그림에서 네모박스는 Entity, 그리고 가장 첫 번째 속성은 PK

이 네 가지 개념을 잘 이해해두자

 

 

 

 

 

< 데이터 모델링 마인드 >

 

메모리를 효율적으로 사용해야 함

읽는 순서를 바꾸거나, fact table 을 어떻게 설계하는지에 따라 메모리 효율이 달라짐

메모리 효율이 좋아지면 다른 사용자와 공유할 메모리가 더 많아지고 더 많은 일을 처리할 수 있게 됨

 

 

 

 

 

 

< 논리 데이터 모델링 >

 

객체란, 처리를 위해 메모리에 올린 데이터

 

 

논리 데이터 모델링은 Entity(테이블) 를 파악하는 작업으로 시작

Entity 란, 정보를 갖고 있거나 그에 대한 정보를 알아야 하는 유무형의 사물이나 객체

"정보를 갖고 있는 thing" 이라고 이해하면 됨

 

 

 

 

< Entity 특성 >

 

 

Entity 는 2 가지 특성이 존재함. 이 두 가지 특성이 없으면 Entity 가 아님

이 두 가지 특성은 데이터의 '무결성'을 지키기 위한 최소한의 안전장치가 됨

 

- 상호 배타성(Mutual Exclusivity) : 모든 인스턴스는 하나의 Entity에만 속해야 함

  하나의 데이터(Instance)는 논리적으로 단 하나의 엔티티에만 소속되어야 함.

  Entity 간의 경계가 모호하면 데이터가 중복되고 정합성이 깨지게 됨

  예를 들어, A table 에 내 이름 정보가 있는데 B table 에도 내 이름 정보가 있으면 안 됨

  (이런 경우 테이블 하나를 PK-FK 로 묶어 사용해서, 중복된 정보를 줄여야 함)

  '커피'라는 정보가 음료table 에도 들어갈 수 있고 각성제table 에도 들어갈 수 있는데 이렇게 만들면 안 됨

  나중에 커피 정보 찾을 때 어떤 테이블에서 찾아야 하는지 모르게되니까

 

- 식별성(Identifiability) : Entity 내에 포함된 모든 인스턴스들은 유일한 식별자에 의해 식별 가능해야 함. PK 말하는 거임

  Entity 는 무조건 PK 를 포함해야 함. 그래서 row(instance) 를 유일하게 식별해낼 수 있어야 함

  식별성을 갖추지 못하면, 데이터 update, delete 를 할 수 없게 됨

  동일한 값을 갖는 여러 instances 에서 내가 원하는 것만 업데이트 할 수 없게 되니까

 

 

 

 

 

 

 

< Entity 유형 >

 

Entity 는 3 가지 유형으로 존재함

 

- Fundamental Entity : 특정 범주에 속하지 않는 기본 개념(특성) 정보를 포함하는 Entity

  정보 처리를 위해 기본적으로 존재하는 코드성 Entity

  물리적 실체가 있음 (사람, 물건)

  다른 Entity 에 의존하지 않고 독립적으로 생성될 수 있어야 함

  예를 들어, 강사 Entity - 가르치는 강의가 없어도 시스템에 등록될 수 있음

  상품 Entity, 고객 Entity, 계좌 Entity 등

 

- Conceptual Entity : 업무 처리를 위한 무형의 개념/과정을 체계화 시킨 Entity

  눈에 보이진 않지만, 데이터를 분류하거나 관리하기 위한 규칙을 정의할 때 사용되는 Entity

  예를 들어, 강의 카테고리 Entity - 프로그래밍, 자료구조 등 '카테고리' 자체는 보이지 않지만 강의를 논리적으로 구분지어줌

  구독 플랜 Entity - 서비스의 정책을 (실체는 없지만) 데이터화함

  부서 Entity - 눈에 보이지 않지만 A부서, B부서 등 체계화 가능

  전공 Entity, 학기 Entity, 등급 Entity, 거래 상태 Entity 등

 

- Associate/Intersection Entity : 두 개 이상의 Entity 를 결합할 때 사용되는 Entity.

  두 Entity(Entity 종류에 상관없음) 사이에서 일어나는 '이벤트'를 기록하는 Entity

  예를 들어, 수강신청(Enrollment) - 학생 Entity 와 강의 Entity 를 같이 묶어주는 역할

  장바구니 - 고객Entity 와 상품Entity 를 묶어주는 Entity

  결제내역 - 고객 Entity 와 주문 Entity 를 묶어주는 Entity (이력이 저장됨)

 

Associate Entity 는 Entity 와 Entity 간 M:N 관계를 연결짓기 위해 사용됨

(RDB 는 Associate Entity 없이 M:N 를 표현할 수 없음)

 

 

M:N 관계 예: 한 명의 학생은 여러 강의를 들을 수 있음(1:N). 

하나의 강의는 여러 학생들에 의해 수강됨(M:1)

이 둘을 연결하는 '수강신청' Entity 는 M:N이 됨.

이 Associate Entity 는, 양 쪽 Entity로부터 PK 를 FK 로 가져와서 자신의 PK 로 사용하고, 연결 정보를 row 로 표현함

M:N 관계를 엉성하게 모델링해두면, 최악의 경우 CARTESIAN JOIN 이 발생할 수 있고 성능 악화로 이어짐

반대로 말하면, Catesian product 를 피하는 방법으로 associate entity 를 사용할 수 있음

 

 

 

Fundamental Entity 는 데이터의 근간(Master)

Conceptual Entity 는 데이터의 분류 및 정의

Associate Entity 는 의존적관계 및 트랜잭션 기록

 

데이터 모델링을 처음 시작할 때, Fundamental Entity 를 먼저 찾고

그 주변에 Conceptual Entity 를 세우고,

마지막으로 둘 사이의 상호작용을 Associate Entity로 정의해볼 수 있음

특히 Associate Entity는 Fact Table의 모태가 되는 경우가 많음

예를 들어, 수강신청 Entity에 수강료, 신청일시 같은 측정값(Measure)이 붙기 시작하면 Fact 데이터가 됨

 

 

 

 

 

 

 

< Entity 구분 >

 

PK-FK 로 연결된 두 Entity 를 부를 때, 상위 Entity, 하위 Entity 라고 부르는 경우가 있음

영어로는 Super Type Entity, Sub Type Entity

 

 

상위 Entity : 다른 Entity에 의해 PK 가 FK 로 사용된(연결된) Entity. 위 예제에서 '고객 Entity', '부서 Entity', '특기 Entity'

하위 Entity : FK 를 갖고있는 Entity (=다른 Entity의 PK 를 FK 로 가지고 있는 경우). 위 예제에서 '계좌 Entity', '사원 Entity'

 

하위 Entity 가 상위 Entity 가 될 수 있음 (하위 Entity 가 다른 Entity와 관계를 맺게되는 경우)

위 예제에서

고객Entity 가 상위, 계좌Entity 가 하위,

계좌Entity 가 상위, 거래Entity 가 하위

즉, 계좌Entity 처럼 Entity 는 상위도, 하위도 될 수 있음

 

모든 Entity 는 관계로 맺어지므로, 모든 Entity 들은 상위/하위로 구분이 지어지게 됨

 

 

 

 

 

 

 

< Entity 정의 >

 

Entity 명칭, Entity 설명, Entity 범주(카테고리), 약어 및 동의어, 데이터 출현 건수 및 예상 변화 등을 고려하자

예를 들어,

Entity 이름 : 단수의 의미있는 이름으로 명명

상호배타성 : 하나의 정보는 하나의 Entity 에 들어가도록(필요한 정보 찾을 때 어떤 Entity에 있는지 바로 알 수 있도록)

크기 및 사용성 : Entity의 총 길이, 사용 빈도, 메모리 사용량 등을 고려. 성능을 올리기 위함

정규화 : 얼마나 정규화 되어있는지

...

 

 

 

 

 

< Entity 사례들 >

 

1.

 

a) 공통 코드 Entity 에 0으로 시작하는 코드는 전산실, 1로 시작하는 코드는 방송실,.. 

이렇게 하면, 공통 코드 Entity 를 읽고 프로그래밍으로 '0으로 시작하는가? 전산실' 이렇게 따로 처리를 해줘야 함

데이터 처리할 때는 추가적인 프로그래밍 없이 쿼리를 할 수 있어야

따라서, 하나의 Entity 에 여러 의미를 갖도록 하지 말자

 

b) 공통 코드 Entity 를 프로그래밍 없이 관계를 맺어서 사원 테이블에 적용하려고 하면, 관계가 너무 복잡해짐

이것도 안 좋은 설계임. 관계가 너무 복잡해지지 않도록 하자

 

 

c) 부서, 직종 등을 각각의 Entity 로 잘게 나눠서, 각각 관계를 맺도록 함

쿼리 퍼포먼스는 a, b 에 비해 좋을지 모르나,

Entity 가 늘어나면 늘어날수록 관리하기가 힘들어짐

따라서, 논리적 모델링에서 Entity 가 늘어나는 경우도 고려해야 함

 

d) 핵심적인 Entity 만 따로 만들어두고(부서, 직종, 직위), 나머지들은 공통 코드 Entity 로 하나로 묶어서 사용

이러면 Entity가 늘어나는 일을 방지할 수 있음 

 

 

 

 

단일 사례를 각각의 Entity 로 만들면, 사례가 늘어날수록 Entity 도 같이 늘어나서 확장성이 떨어짐.

성능도 안 좋아지고 운영도 복잡해짐

따라서 단일 사례를 Entity 로 만들지 말고, 하나의 Entity 로 만들어서 관리하는 게 좋음

 

 

 

 

 

 

 

a) 품목 Entity 는 자주 자주 쿼리되는 Entity 임. 대중소구분 Entity 들이 모두 연결되어 있으니 성능이 좋지 않음

하지만 소구분Entity 가 없는 품목을 저장할 수 있음

 

b) 자주 쿼리되는 품목 Entity 하나의 Entity(소구분)만 연결되어 있어서 쿼리 성능이 좋으나,

대중소Entity 들의 PK가 계속 길어지는 단점이 발생

 

 

c) PK 가 길어지지 않도록, 상위 Entity 의 PK 만 유지함

하지만 만약, 품목 Entity 가 중구분Entity 와 join 해야하는 상황이 발생하면 

반드시 소구분 Entity 와 join 해야 함

이것이 성능 상 단점이 될 수 있음

 

d) 그럼 소구분 Entity 를 join하지 않고 바로 중, 대구분 Entity 로 join할 수 있도록, 품목 Entity 에 대중소 FK를 모두 넣으면?

이건 가장 안 좋은 케이스

왜냐면 Circular Dependency/Relationship 가 발생하기 때문.

 

 

예를 들어,

- Entity A: Department (부서) -> 부서를 관리하는 '부서장(Employee)' 정보를 FK로 설정
- Entity B: Employee (직원) -> 직원이 소속된 '부서(Department)' 정보를 FK로 설정
이렇게 되면 A가 B를 참조하고, B가 다시 A를 참조하는 형태가 됨

 

Circular Dependency 를 만들면 어떤 일이 발생하는가?

- 데이터를 처음 넣을 때 문제가 발생

  부서를 만들려면 부서장(직원)이 이미 있어야 하고, 직원을 만들려면 소속 부서가 이미 있어야 하니, 데이터를 넣을 수 없게 됨

- 데이터를 삭제 할 때 문제가 발생

- 쿼리 진행시 잘못하면 무한루프에 빠질 수 있음

 

만약 Circular Dependency 가 발생하면, 아래처럼 해결할 수 있음

- 위 예제에서 "부서장"이라는 관계를 별도의 Entity로 분리하거나 속성을 재정의함
  Employee 테이블에서 dept_id는 유지.

  Department 테이블의 manager_id 는 없애고, Department_History, Manager_Assignment 같은 Associate Entity를 만들어

  "누가 언제부터 언제까지 어느 부서의 장이었는지"를 기록
- 플래그(Flag) 또는 상태값 활용
  물리적인 FK 연결 대신, 비즈니스 로직으로 처리.

  한쪽의 FK 연결을 끊고 Employee Entity 에 is_manager 같은 컬럼을 추가. 이렇게 논리적인 관계만 유지

 

Associate Entity 를 추가하여 Circular Relationship 이슈를 해결하는 예제

 

 

 

 

 

 

 

위 구매의뢰 Entity 에서는 여러 자재를 가져올 수 있고(1:N)

자재 Entity 에서는 여러 구매의뢰에 매칭될 수 있음(M:1)

이렇게 발생되는 M:N 관계는 Associate Entity 등으로 반드시 처리해줘야 함

 

 

 

 

 

 

부동산매물 Entity, 판매자 Entity, 구매자 Entity.... 등등

다양한 역할을 모두 Entity 로 만들지 말라는 이야기임

역할이 추가되면? 예를 들어 중개인 Entity 가 추가되거나, 보험Entity 가 추가되면?

계약Entity 에 끝도없이 추가되기 때문에 관리가 복잡해짐

 

역할을 모두 Entity 로 만들지 말고,

Entity 하나에 몰아넣으라고 말하는 것 같음. 근데 정확하게 이해는 못 함....

추가될 수 있는 부분은 하나의 Entity 로 만들어보자

 

 

 

 

 

 

관계를 맺지 않은 Entity가 없도록 해야 함

모든 Entity 는 다른 Entity 와 관계를 맺어야 함

 

 

 

 

 

 

동의어를 따로따로 Entity 로 만들지 말아야 함

인사관리에서는 사원이라고 부르고

회계관리에서는 직원이라고 부르고

생산관리에서는 작업자라고 부르는데

사실 다 동일한 의미를 갖고 있잖아

그래서 하나의 Entity 를 만들고 공통으로 사용하는 방향이 좋음

특별한 취급이 필요하다면 위에 작업자 Entity  처럼 따로 만들어도 좋음

 

 

 

 

< Entity 관계 정의 >

 

두 개 이상의 Entity 간 명명된 의미있는 연결. 관계.

Entity와 Entity 간 연결은 식별자(PK, FK) 기준으로 설정됨

Entity 간 참조 무결성(Referential Integrity)을 유지하게 해 줌

 

참조 무결성 예) 자식 Entity 는 부모 Entity 가 갖지 않은 값을 가질 수 없음

예를 들어, 부모 Entity(부서)는 다음과 같음

dept_id(PK) dept_name
10 데이터 엔지니어링부서
20 비즈니스 분석부서

 

자식 Entity(직원) 는 다음과 같음

emp_id emp_name dept_id (FK)
101 눈가락 10
102 머릿가락 10
103 손가락 20

 

이 때 부모 Entity 에 없는 값을 이용하여 자식 Entity 에 값을 넣을 수 없음

가령 104, 홍길동, 90 이런 값을 넣을 수 없음 (DB 에서 막음)

 

 

Entity 간 관계를 ERD 로 그릴 때 아래와 같은 기호를 사용

 

| (Mandatory/One): 선 위에 수직선 하나가 있으면 '1' 또는 '반드시 하나'. 숫자로 따졌을 때 하나만 연결됨.

  "연결이 하나만 있을 수 있더라"
O (Optional/Zero): 동그라미는 '0'을 뜻하며, 관계가 없을 수도 있음

  "연결이 없을 수 있더라"
> (Multiple/Many): 세 갈래로 갈라지는 모양(까마귀 발). '다수(Many)'

  "연결이 여럿 있을 수 있더라"

 

 

최소 몇 개, 최대 몇 개가 가능한지 등을 보여주기 위해서 이런 notation 을 사용

 

 

 

 

 

왼쪽이 사원 Entity 이고, 5개의 서로 다른 관계로 Entity 와 연결됨

- 1:1 관계 : 사원과 매니저. 사원과 성별

  사원 한 명이 두 개 이상의 성별을 가질 수 없음. 그래서 1:1 관계가 됨.

  반드시 하나의 instance 와만 매칭됨. 다수 매칭될 수 없음

  사원과 이름의 경우, 이름이 바뀌는 경우가 발생할 수 있어서 1:N 관계로 생각될 수 있음

- 1:0, 1:1 관계 : 사원과 병역사항, 사원과 프로필사진 등

  남사원은 병역 사항이 존재하고 여사원은 존재하지 않음

  프로필사진이 있는 사원도 있고 없는 사원도 있음

- 1:1, 1:N 관계 : 사원과 프로젝트

  사원 하나가 최소 하나 이상의 프로젝트에 참여할 수 있지만

  프로젝트에 참여하지 않은 사원은 없음(1:0은 아님)

- 1:0, 1:1, 1:N 관계 : 사원과 성과

  성과가 없는 사원이 존재할 수 있음

  성과가 존재한다면 무조건 하나 이상 존재함

- 1:N 관계 : 사원과 학력

 

아래 ERD 를 보고 Notation 들을 이해해보자

 

추가로, 신체사항Entity 와 병역사항Entity 는 1:1 관계이기 때문에

사원 Entity 자체에 넣어도 문제는 발생하지 않음

사원 Entity 는 수시로 IO 되고

신체사항, 병역사항은 1년에 두 세번밖에 IO되지 않는데

사원 Entity를 부를 때마다 신체/병역 사항이 계속 불린다면 이건 메모리 낭비가 될 수 밖에 없음

따라서, 자주 접근하지 않는 정보들은 1:1 관계의 Entity 로 만들어서 따로 빼두는 것이 좋음

 

 

 

 

 

 

교차 관계를 Associate Entity 표현하는 것이 아주아주아주아주 중요함

양쪽 Entity 의 PK 를 묶은 FK 두 개를 Associate Entity 의 PK로 사용(이것은 Composite Key 라고 함)

그리고 notation 은, 위 이미지의 빨간 선과 같이 뒤집어서 연결해주면 됨

 

두 개의 FK 중 어느 것을 먼저 두느냐도 성능에 영향을 미침

 

동일한 두 개의 FK 가 Associate Entity 에 두 번 이상 들어가야 하는 경우가 발생하기도 함

Composite Key 를 PK 로 사용하면 두 번 이상 들어가게 만들 수 없음

이런 경우가 발생하면, 두 Entity 의 FK 중 하나를 Associate Entity 의 attribute 로만 참조하고,

Associate Entity PK 를 FK 하나+Surrogate Key 로 만들 수 있음

이렇게 Associate Entity 에 surrogate key 를 사용하는 경우도 발생

 

 

 

 

 

 

 

 

Identifying Relationship : Sub Entitry 가 갖는 FK 가 PK 로 사용됨

  예) 주문Entity - 주문항목 Entity

Non-Identifying Relationship : Sub Entitry 가 갖는 FK 를  PK 로 사용되지 않고 attribute 로 사용됨

  예) 거래처 Entity - 주문 Entity, 주문항목 Entity - 품목 Entity

 

FK 를 PK 로 사용할 지 말지 의사소통 할 때 사용하는 용어라고 함

 

 

 

 

 

두 Entity 간 연결이 두 번 이상 발생하는 경우도 조재함

 

자기 자신과 연결되는 경우도 존재함

한 번 재귀는 괜찮지만, 서너번 이상의 재귀는 성능 하락으로 이어짐

 

 

 

중복 관계는 Associate Entity 를 통해 해결 가능함

 

 

 

 

 

 

 

 

 

 

 

중간에 X 있는 것이 and, 없는 것이 or.

근데 DB 쿼리 작성할 때는 or 되도록 사용하지 말라고 함

and 로 바꿔서 처리하라고....

(물론 누가봐도 성능상 or 사용이 유리할 때는 or를 사용해야지)

 

 

 

 

 

 

 

 

 

< identifiers >

 

- SuperKey : 유일성을 보장하는 키 묶음. 키가 엄청 길어지는 것은 신경쓰지 않는 슈퍼맨임...

  학번은 SuperKey가 됨

  주민번호도 SuperKey 가 됨

  학번+주민번호 도 SuperKey 가 됨

  학번 + 주민번호 + 이름 도 SuperKey 가 됨

  유일성만 보장한다면 어떻게 연결하던 SuperKey 가 됨

 

- CandidateKey : SuperKey 중에서 minimality 를 보장하는 키. CandidateKey 중에서 PK를 선택함

  학번은 SuperKey 중에 가장 짧기 때문에 CandidateKey가 됨

  주민번호도 가장 짧기 때문에 CandidateKey 가 됨

  학번+주민번호는 짧지 않기 때문에 CandidateKey가 될 수 없음

 

SuperKey, CandidateKey 는 논리적인 개념일 뿐이고 DB 에 직접 쓰이지 않음

 

- PrimaryKey : CandidateKey 중에서 실제로 DB 에 사용되는 하나의 키

  모든 Entity 에서는 PK 가 반드시 존재해야 함

  PK 는 null 이 되지 말아야 하며, 모든 instnaces 를 구분할 수 있어야 함

  가능한 짧게 만들어야 하며(indexing 성능 때문에) 단순하게 만들어야 함(너무 많은 컬럼 조합하지 말라는 말)

  컬럼 하나로 만들거나, 두 개 컬럼 조합해서 만들거나, FK 랑 조합해서 만들거나, surrogatekey 랑 조합해서 만들거나

  참고로, PK 는 업데이트가 가능함(!). update table set mypk = 0 where mypk = 1; 이 실제로 동작하는 말임

  업데이트 된다고 해서 막 바꿔도 된다는 말은 아니고, PK 한 번 만들고나면 최대한 바꾸지 말아야 함

 

- AlternateKey : CandidateKey 중에서 PK 가 되지 못한 키.

  sort, if, where 등에 자주 사용될 수 있으며, 자주 사용된다면 index 를 추가해서 사용함.

 

 

 

 

 

윗부분은 품목분류 Entity 와 품목 Entity 가 상하위 관계를 갖고

품목 Entity 와 재고영역 Entity 사이에 M:N 관계가 발생해서 재고 Associate Entity 를 만듦

근데 재고 Entity 의 PK 가 너무 커져버림

 

그래서 차라리 상위 Entity 에서부터 PK 를 줄여서, 

Associate Entity 의 PK 가 줄어들 수 있도록 조치함

 

 

 

 

 

 

 

 

 

품목 Entity 와 구매발주 Entity 사이의 구매발주품목 Associate Entity 가 생성됨

근데 품목코드 FK 는 attribute 로만 사용되었고,

구매발주번호 FK( + 구매발주품목순번 surrogate key) 는 PK로 사용됨

이건 왜 이렇게 했는가? 구매발주Entity 와 구매발주품목Entity 를 자주 묶어서 쿼리한다는 걸 알고 있어서.

이렇게 Associate Entity 에서는, 자주 사용되는 FK 만 PK 로 올려서 사용하는 센스를 발휘할 수 있음

 

추가로, 입고 Entity 에서 모든 FK 를 다 attribute 로 내렸음.

모든 FK 를 PK로 사용하면 복잡해지기 때문에

PK 를 surrogate key 로 만들어두고 사용하는 예제임

 

 

 

 

 

 

 

 

 

여러 컬럼의 조합으로 PK 를 만들 때, 조합 순서도 퍼포먼스에 영향을 끼침

실적1 Entity 는 지점코드-상품코드-분류... 순서이고

실적2 Entity 는 년도-월-지점코드-상품코드... 순서임

 

 

하지만 쿼리의 where 절에 무엇이 들어가냐에 따라 쿼리 성능이 달라짐

where 절에 '코드'가 포함되어있는데, 이 '코드'컬럼이 PK 의 앞쪽에 위치한 실적1Entity 의 성능이 더 좋음

즉, PK 를 구성하는 컬럼 중 앞쪽에 있는 컬럼으로 where 해야 성능이 좋다는 것을 이해하고 있어야 함

 

 

 

 

 

 

 

 

위 제품 Entity 보다는

아래 제품 Entity 가 더 나은 설계가 됨

 

'제품코드' 라는 컬럼은 제품구분,생산공장,순선이 모두 조합된 정보를 갖고 있음

 

'생산공장별로...' 라는 쿼리를 수행한다면 

위 제품 Entity 는  PK 를 substring 으로 잘라서 사용해야하는데 이건 성능이 나오지 않음

아래 제품 Entity 처럼, 제품코드는 그대로 갖고있되

잘라서 써야하는 부분들(제품코드, 생산공장)을 attribute 로 또 만들어서 사용함

그럼 PK 를 substring 하지 않아도 되기 때문에 성능이 나옴

 

추가로, 제품코드, 생산공장 정보를 갖고 있는 Entity를 따로 만들면 나중에 쿼리할 때 좋음

예를 들어, 제품Entity 가 10만개 정보를 갖고 있고 제품구분Entity 는 10개 정보를 갖고있다고 하자

제품Entity 에서 1인 것을 찾아 full scan 하는 것보다,

제품구분코드 1인 것을 찾을 때, 제품구분 Entity 에서 먼저 1을 찾고 제품 Entity와 join해서 찾는 게 빠르다고 함

(join할 때도 full scan 하지 않나...?

index 가 없는데, 제품 Entity 에서 1을 수집할 때 join 으로 full scan 을 피할 수 있나?)

 

 

위와 비슷한 예제를 하나 더 살펴보자

 

 

 

제품 Entity 의 '제품코드'는 여러 컬럼의 조합으로 이루어짐(브랜드,복잡종류,년도,시즌.....)

a 는 쿼리할 때 PK 를 substring 으로 잘라써야하니 성능이 좋지 않고

b 는 PK 가 너무 길고

c 가 적절한 모델링이 될 수 있음

추가로 e 처럼 다른 Entity 를 설정하고 FK 로 연결하면 쿼리 성능이 더 좋아진다는 내용

 

 

 

 

 

 

 

위 사원 Entity 의 경우, 사번 하나 당 운전면허번호가 하나만 들어오게 되어있음

만약 운전면허번호가 2개 이상이라면?

이런 경우, 운전면허번호를 위한 Entity 를 하나 더 만들어서 2개 이상의 정보를 넣을 수 있도록 하자

 

 

 

 

 

 

 

 

 

 

 

 

 

개발 영어 공부1 : https://eyeballs.tistory.com/683

 

 

Spark was compiled for 2.13 스파크는 2.13 용으로 컴파일되었다.
It determines when to remove and request executors. 결정하다.
If the jobs at the head of the queue don't need to use the whole cluster, later jobs can start to run right away 대기열의 맨 앞에 있는 jobs
후속 jobs
then later jobs may be delayed significantly
significant computing resources may be required.
상당히 지연될 수 있다.
상당한 컴퓨팅 자원이 요구될 수 있다.
This feature is disabled by default. 기본적으로 비활성화되어있다.
Newly submitted jobs go into a default pool. 새롭게 제출된 작업들은 default pool에 들어간다.
Jobs run in FIFO order
Jobs run in order.
Automate A, B, and C in order of importance.
data is stored in chronological order
FIFO 순서로 작업이 실행된다.
순서대로 작업이 실행된다.
중요한 순서대로 자동화하라
시간순으로 저장되어있다
both of these together make up the node
Distributed storage refers to a storage architecture made up of multiple computers and disks.
노드를 만든다.
다양한 컴퓨터와 디스크로 구성된 저장 아키텍처
The same is true of the C node. C노드도 마찬가지다.
Our managers deal with all kinds of clients every day 매일 다양한 clients 를 상대한다.
In my previous project I carried out the responsibilities of... 나의 이전 프로젝트에서, 이러이러한 책임을 수행했다.
Project managers usually estimate new projects by analogy 유사사례를 통해 신규 프로젝트를 추정한다.
I improved my time management and organizational skills. 시간 관리 및 시간 정리 능력을 향상시켰다.
the server performs instructions written in code. 명령을 수행한다.
use only the numbers in given array.
Cardinality refers to the number of unique values in a given dataset.
주어진 배열 내 숫자만 사용하라
카디널리티(Cardinality)는 특정 데이터 집합에서 고유한 값(unique values)의 개수를 의미한다.
assigned the number 33 to age variable. 나이 변수에 33을 할당했다.
I created an array of strings. 문자열 배열을 생성했다.
Debugging is to investigate the program and fix bugs. 프로그램을 조사하는 것이다.
A program crashes when you divide by zero. 프로그램이 중단된다.
declared a function and implemented it. It works well!  함수 하나를 선언했고 구현했다. 잘 동작한다.
instantiated another object of the Student class. 또 다른 학생 클래스 객체를 인스턴스화했다.
iterated(loop) through every element in the list. 리스트 내 모든 요소를 순회했다.
Processing is manipulation of data by a computer 컴퓨터에 의한 데이터 조작이다.
Raw data can be converted into JSON format. Josn 형태로 변환될 수 있다.
Maintainability : It should be stable when the changes are made 변경사항이 적용되었을 때 안정적이어야 한다.
You need a dedicated work space 전용 작업 공간
Let's move our meeting back an hour. 한 시간 미루자
She moved the meeting up a day. 미팅을 하루 앞당겼다.
The meeting was rescheduled for Thursday. 회의가 목요일로 재조정되었다.
From a subjective perspective. 주관적인 관점에서
We will meet in a week and synchronize on the progress. 진행 상황을 맞춰보자.
Big data enables you to gather data from many sources. 데이터를 수집할 수 있게 한다.
A kafka topic is identified by its name
Each broker is identified with its ID.
카프카 토픽은 이름으로 식별된다.
The sequence of messages is called a data stream
Sequential messages
received messages in sequence.
processing data sequentially is necessary
메세지의 순서를 데이터 스트림이라고 부른다.
연속된 메세지들
순서대로 수신한 메세지들
연속으로 데이터를 처리하는 것이 필요하다.
Topics are split in partitions. 토픽은 파티션으로 나뉘어진다.
Each message gets an incremental id, called offset.
'Append' adds only the newly arrived data incrementally
하나씩 증가하는 id
'Append' 는 새로 추가된 데이터를 증분으로 추가한다.
Kafka topics are immutable 토픽들은 불변한다.
Data is kept only for a limited time.
Data is maintained only for a limited time.
Data remained only for a limited time.
데이터는 제한된 기간 동안만 보관된다.
데이터는 제한된 기간 동안만 유지된다.
데이터는 제한된 기간 동안만 남아 있는다.
Over time, the kafka clients have been changed. 시간이 지남에 따라...
The processing of rapidly increasing data is entrusted to Hadoop.
I delegated the task to Hadoop
빠르게 증가하는 데이터 처리를 하둡에게 맡긴다.
하둡에게 그 일을 위임했다.
There are two main methods for data transmission.  
The "streaming type" continuously transmits data as it is generated, in real time. 실시간으로 생성되는 데이터를 끊임없이 보내는 방법이다.
Data collected over the past 30 minutes is aggregated
If you want to graph the event trend over the past hour..
지난 30분동안 모은 데이터들이 집계되었다.
과거 1시간의 이벤트 수 추이를 그래프로 만들고 싶으면..
To analyze data from the past 3 years 지난 3년간의 데이터를 분석하기 위해
Amazon S3 is a representative example of object storage. 대표적인 객체 스토리지다.
it can increase data capacity in the future. 향후 데이터 용량을 증가시킬 수 있다.
Most people are accustomed to using SQL SQL 사용에 익숙하다.
This series of procedures is called the ETL process 일련의 절차를 ETL 프로세스라고 부른다.
Batch processing is executed according to a fixed daily schedule 고정된 일일 일정에 따라 실행된다.
If an error occurs, the administrator is notified. 관리자에게 알려진다.
System failures can occur during big data processing.
Therefore, it is necessary to implement functions to handle and retry tasks when errors occur.
처리하는 기능을 구현하는 것이 필수다.
Data collected throughout the day is aggregated overnight to generate reports. 하룻동안 수집된 데이터들은 밤사이 집계된다.
Unprocessed raw data is stored in a data lake, and only the necessary data is retrieved and used later. 미가공한 원시 데이터가 data lake 에 저장된다.
그리고 필요한 데이터만 추출된다.
Data engineers are responsible for building, managing, and automating the systems. 데이터 엔지니어는 책임을 진다.
It’s best to start with a small system and gradually scale it up over time. 나중에 단계적으로 확장해가는 것이 좋다.
In the early stagesmanually collecting and analyzing data without automation is called ad hoc analysis. 시작 단계에서..
Searching for data that meets specific criteria  특정 기준을 충족하는 데이터 검색하기
values in the 'time' column can be tricky to handle time 컬럼값은 다루기가 까다롭다
The same aggregation is repeated on a regular schedule—weekly or monthly—to observe trends over time. 1개월 혹은 1주일마다 정기적인 일정으로 동일한 집계를 반복하고 그 추이를 관찰한다
the number of ad impressions. 광고 노출 수
The number of customers who used the service in a day.
The number of customers who used the service within a day.
하루에 서비스를 이용한 고객 수 (하루 전체. 통으로)
하루 이내에 서비스를 이용한 고객수 (24시간 이내에)
Making decisions based on objective data is called data-driven decision making. 객관적인 데이터를 근거하여 판단하는 것을 '데이터 기반 의사 결정'이라고 한다.
the values in A column are generally higher/lower/similar to the values in B column. 전체적으로
As long as you have organized numerical data 정리된 숫자 데이터가 있다면
names are listed in rows, and sales are listed in columns. 행 방향으로 나열되고, 열 방향으로 나열된다.
the numeric data appears at the intersections of rows and columns 행과 열의 교차점
large datasets that can't fully fit in memory
Load 
all the data into memory.
메모리에 다 들어가지 못하는 큰 용량의 데이터
모든 데이터를 메모리에 올린다.
If the wait time for aggregation increases, all processes slow down. 대기시간이 늘어나면, 모든 작업들이 느려진다.
your system needs to be designed for it from the start. 처음부터 그렇게 디자인되어야 했다.
fast data processing is described as having low latency. '지연시간(latency)이 적다'고 표현된다.
a sharp drop/improvement in performance 급격한 성능 저하/향상
The amount of data that can be processed within a certain period of time is called "throughput". 일정 시간 내에 처리할 수 있는 데이터의 양을 처리량(throughput)이라 한다.
The time you wait for data processing to complete is called "latency". 작업이 끝날 때 까지 대기하는 시간을 지연시간(latency)이라 한다.
The presence or absence of indexes
Which option to choose depends on the situation.
인덱스 유무
어떤 옵션을 선택할지는 상황에 따라 달라진다.
a query is broken down into many smaller tasks 다수의 작은 태스크로 분해된다.
you need to scale both CPU and disk resources in a balanced way. 균형있게 자원을 늘려야한다.
exploring the data through repeated trial and error. 반복적인 시행착오를 통해
In contrast to ad hoc analysis, you can run queries on a regular schedule to generate reports. ad hoc 분석과 대조적으로..
you want to take your time and carefully examine the data. 시간을 갖고 차분히 데이터를 보고 싶다.
Metric B is updated once a day. B 메트릭은 하루에 한 번 업데이트 된다.
improvements in computing power 컴퓨팅 성능 향상
There are more/fewer cases now where building a data mart is unnecessary. 이러한 경우가 늘어나고/줄어들고 있다.
Normalization involves splitting tables as much as possible and linking them using foreign keys.  
Denormalization involves combining tables as much as possible.  
tables are categorized into fact tables and dimension tables.  
Fact tables store data that accumulates over time. 시간에 따라 증가하는 데이터가 저장된다.
Dimension tables typically store attributes used to categorize the data.  
A model where a fact table is surrounded by multiple dimension tables is called a star schema.  
Files are replicated across multiple machines to increase redundancy. 중복성을 높이기 위해 파일을 복사한다.
jobs are preferably executed on nodes close to the data. 가급적, 데이터와 가까운 노드에서 실행한다.
spontaneously
simultaneously
자발적으로
동시에
resource contention(competition) occurs between jobs 자원 쟁탈(경쟁)
they run only when no one else is using the resources. 누구도 자원을 사용하지 않을 때만
Spark keeps intermediate data in memory
It is safer to process data in an intermediate table first 
중간 데이터를 메모리에 보존한다.
중간 테이블을 만들어 처리하는 게 안전하다.
problems arise when aggregating large amounts of data over a long period. 장기간에 거쳐
data is evenly distributed across all nodes 균형있게 분산되어있다.
storage and compute nodes are tightly coupled 밀접하게 결합되어있다.
it either waits for resources to free up or fails with an error. 메모리가 생길 때까지 기다리거나
memory usage doesn’t increase proportionally 비례하여 늘어나지 않는다.
memory consumption remains nearly constant 메모리 사용량은 거의 일정하게 유지된다
You can aggregate data with millions of records in under one second 수백만 레코드를 갖는 데이터를 1초 미만으로 집계할 수 있다.
Even if a partial failure occurs, processing can continue as a whole 부분적으로 장애가 발생해도, 전체적으로 처리를 계속할 수 있다.
Tez is a replacement for MapReduce and inherits its fault tolerance.
Tez is an alternative to MapReduce.
Tez 는 MapReduce 를 대체하는 것이며, 그 내결함성을 계승하고 있다.
Presto is the complete opposite of Hive presto 는 hive 와 완전히 반대입니다
Presto is specialized for executing interactive queries. Presto 는 대화식 쿼리의 실행에 특화되어 있다.
excessive usage can prevent other queries from running.
Excessively reducing cardinality can lead to significant information loss
무리한 사용
카디널리티를 무리하게 낮추면 원래 있던 정보가 크게 손실된다
it handles schema changes more flexibly. 스키마 변동에도 유연하게 대처할 수 있다.
frequent read/write operations on small amounts of data 빈번하게 소량의 데이터를 읽고 쓰는 것
It increases the rate of unexpected errors.
the likelihood of unexpected errors increases.
예상치 못한 오류 발생률을 높인다.
It's a design issue rather than a performance problem.
Massive data should be divided and processed in parts rather than all at once
성능 문제라기보다는 설계 문제이다.
한 번에 처리하기보다는 부분으로 나눠서 처리해야한다.
What is the optimal file size for efficient processing? 효율적으로 처리할 수 있는 파일이 크기는 얼마나 될까?
These two differ entirely in both technical characteristics and tools used, so you must understand their nature and use them accordingly. 이 둘은 기술적인 특성도, 사용되는 도구도 전혀 다르므로 그 성질을 이해한 다음에 구분해서 사용해야 한다.
When handling large volumes of data, break tasks into monthly or daily units to prevent any single task from becoming too large. 한 달 혹은 하루 단위로 전송하도록 태스크를 분해하여, 너무 커지지 않도록 막는다.
Fluentd only sends messages in one direction 일방적으로 발송하는 것밖에 하지 못한다
mobile apps often go offline
the device is back online.
모바일 앱은 오프라인이 되는 경우가 종종 있다.
다시 온라인 상태가 된다.
It can focus solely on its own tasks while leaving the rest to the shared system. 작업에만 오롯이 전념할 수 있고, 나머지 작업은 공통 시스템에 맡길 수 있다.
the two are in a trade-off relationship 둘은 트레이드오프 관계에 있다.
you just reached a performance limit 성능 한계에 도달했다.
regulate the data write rate. 데이터 쓰기 속도를 조절하라
you need to decide in advance how to operate the system in its absence. 그것이 없을 때 어떻게 시스템을 운용할지 미리 결정해야한다.
Only keep the IDs received within the last hour, and allow duplicates that arrived later.
Allow duplicates for late-arriving messages.
최근 1 시간 동안 받은 ID 만 기억해두고, 그보다 늦게 온 메세지의 중복은 허용한다.
The time a message is generated on the client is called “event time,”  (on the client side)  
the time the server processes the message is called “process time.”  
the data is arranged in a contiguous layout. 데이터가 연속적으로 배치되어있다.
Eventual consistency guarantees that all replicas will eventually converge to the same value over time. 시간이 지나면 결국 동일한 값으로 귀결된다.
Strong consistency guarantees that all read operations reflect the most recent write. 가장 최근의 쓰기를 반영한다.
a human intervenes to resolve the issue. 사람이 개입하여 문제를 해결한다.
Some tasks can cause new problems if they are not completed by the scheduled time 예정된 시간까지 끝내지 않으면 새로운 문제를 일으키는 태스크도 있다.
Let's finish it within the allotted time. 정해진(할당된) 시간 내에 끝내자.
There are tools that notify you when a task exceeds its expected execution time. 작업이 예상 실행 시간을 초과할 때 알려주는 도구가 있다.
It is important to anticipate potential unexpected errors in advance 예기치 못한 오류 발생 가능성을 예상하는 것은 중요하다.
Setting the retry interval of a task to 10 minutes 작업의 재시도 간격을 10분으로 설정
“Backfill” refers to rerunning tasks over a specific period by changing the date parameter in sequence. ‘백필’이란 파라미터에 포함된 날짜를 순서대로 바꿔가면서 일정 기간의 태스크를 다시 실행함을 의미한다.
You can test backfill gradually 테스트 삼아 조금씩 백필을 실행할 수 있다.
In Airflow, scripts must be written with atomicity and idempotency Airflow 에서는 원자성과 멱등성을 갖춘 스크립트를 작성해야 한다.
it helps improve stability. 안정성을 높인다.
An execution with this property is called an idempotent operation.
이런 특성을 지닌 실행을 idempotent operation 이라고 한다.
'replacement' yields the same result even when repeated '치환'은 반복해서 실행해도 동일한 결과를 산출한다.
Increase the number of retries while gradually expanding the interval between them 재시도 횟수를 늘림과 동시에, 조금씩 재시도 간격을 넓혀나가라
automatic retries must be disabled, and recovery should be done manually in case of failure.
자동 재시도는 반드시 무효로 하고, 오류 발생 시 수작업으로 복구한다.
Adjust each task so that it has an appropriate size. 각 태스크가 적절한 크기가 될 수 있도록 조정한다.
nodes are connected by arrows, 
and these connections never form cycles.

노드와 노드가 화살표로 연결되며
각 노드 연결이 순환되지 않는다.
We can reprocess data starting from 7 days ago. 7일 전 데이터부터 재처리할 수 있다.
fast-response database is placed in the serving layer 서빙 레이어에 응답이 빠른 데이터베이스를 설치한다
Since the results of stream processing are used only temporarilyslight inaccuracies are acceptable. 스트림 처리의 결과는 일시적으로만 사용되며, 정확하지 않아도 큰 문제가 없다.
Handling messages with a large gap between processing time and event time is referred to as the out-of-order data problem. 프로세스 시간과 이벤트 시간의 차이가 큰 메세지를 처리하는 것을 ‘out of order’ 데이터 문제라고 불린다.
they must be sorted by event time before aggregation 이벤트 시간 순서로 정렬하고 집계한다.
Therefore, the system must retain the state of past events 
and re-aggregate the corresponding window whenever new data arrives.
때문에 과거 이벤트의 상태를 보존하면서, 데이터가 도달할 때마다 해당 윈도우를 재집계한다.
Since data cannot be stored indefinitely
data that arrives too late beyond a certain time threshold is ignored.

데이터를 무한히 계속 보관할 순 없으므로 일정 시간 이상 늦게 온 데이터는 무시한다.
In ad hoc data analysis, interpreters are preferred. ad hoc 데이터 분석에서는 인터프리터를 선호한다.
Each tweet is formatted as JSON data with a variable length.
각 트윗은 길이가 일정하지 않은 json 데이터로 되어 있다.
Virtual machines allow the entire team to share a consistent setup 팀 전원이 같은 환경을 공유할 수 있게 해준다.
extracting data for a specified period
The error occurred under the specified conditions.
명시된 기간 만큼의 데이터 추출하기
명시된 조건에서 발생했다.
overwriting a designated partition 지정된 파티션 덮어쓰기
As long as the parameters remain the same 파라미터만 같다면
The functions executed at this time are serialized and lazily evaluated 이 때 실행되는 함수는 직렬화되어 지연 평가된다.
If the schedule is set to @daily, the task for January 1st is executed at the moment January 2nd begins.
there is a one-day gap 
스케줄이 @daily 라면, 1월 1일의 태스크가 실행되는 것은 다음 날 1월 2일이 되는 순간이다.
1일의 차이가 있다.

if more tasks are queuedthey are put on hold until slots become available. 그 이상의 태스크가 등록되면 빈 자리가 생길 때까지 실행이 보류된다.
Adjust task durations so that each one doesn’t take too long 각 태스크의 실행 시간이 길어지지 않도록 조절하라
It hasn't been that long. 그렇게 오래되진 않았어.
keep the system in a relaxed state.
항상 여유 있는 상태를 유지하라
By automating what was previously a manual reprocessing task 이전에 수동으로 처리해야 했던 작업을 자동화함으로써
a single re-run handles all necessary steps 필요한 모든 과정을 처리했다.
If I were asked to handle tuning, my approach would be:
first, measure and identify the bottleneck by profiling,
then research best practices or consult documentation,
and validate improvements step by step.
 
I’d definitely want to confirm the original intent before making any changes. 반드시 원래 의도를 확인하겠다.
I was tasked with building a data pipeline 데이터 파이프를 구축하게 되었음
To ensure idempotency, it deletes existing data for each date and regenerates it
날짜 단위로 기존 데이터를 삭제하고 새로 데이터를 만듦
there was no process in place to verify data quality.
데이터 품질 검사를 위한 프로세스가 마련되어 있지 않았다.
I identified and resolved the root causes of the inconsistency 원인을 발견하고 해결하였다.
The source team’s table had a different primary key (PK) configuration, causing duplicate records. 데이터 복제를 발생시켰다.
Some data was missing because their encryption logic malfunctioned during transmission
암호화 로직이 잘못 적용되어있었다.
we began receiving accurate data consistently.
정합성있는 데이터를 받을 수 있게 되었다.
I carried out a data cleansing process to remove or obscure PII where it would not affect business decisions.
PII 를 제거하거나 가리기 위해 클렌징 작업을 수행했다.
I masked the middle part of names with stars to obfuscate the PII. 모호하게 하기 위해 이름 중간 부분을 별표로 가렸다.
I applied a retention policy to PII, performing a soft delete for any PII older than three months from the current date. PII 에 retention policy 를 적용하여 현재 날짜로부터 3개월이 지난 모든 PII에 대해 소프트 삭제를 수행했다.
I checked cross-version backward compatibility within the EMR environment to ensure there would be no issues after the upgrade. 업그레이드 후 문제가 발생하지 않도록 EMR 환경 내에서 버전 간 하위 호환성을 확인했다.
I then provisioned a new EMR cluster with the latest version 그런 다음 최신 버전으로 새 EMR 클러스터를 프로비저닝했다.
There were KTLO (Keep The Lights On) jobs scheduled by time, similar to crontab
crontab 처럼, 시간으로 스케줄링 해 둔 KTLO 작업들이 존재함
if an upstream job failed, it caused downstream failures.
상위 작업이 실패하면 하위 작업의 실패를 초래했다.
I modified the code to be idempotent 코드를 멱등성을 갖도록 수정했다
This reduced human error and improved operational efficiency. 인적 오류도 감소하고 운영 효율성이 향상되었다.
I will proactively seek out and learn technologies I haven't used before. 사용해 보지 않은 기술을 적극적으로 찾아 배울 것이다.
I will invest time to take online courses, research best practices, and get hands-on experimentation. 온라인 강좌 수강, 모범 사례 연구, 그리고 직접적인 실험을 위해 시간을 투자할 것임
I will ensure no disruption to my work. 업무에 차질이 없도록 하겠다.
work with BA and DS teams, and respond to their requests.
업무요청 대응하기
I took over the task of synchronizing data 데이터 동기화 작업을 인수인계 받았다
Occasionally, incorrect data would come in from the source table 가끔씩 소스 테이블에서 잘못된 데이터가 들어오곤 했다
we only found out days later. 우리는 며칠이 지나서야 알게 되었다.
he told me to retrieve the data for that date again 
and move it to the target table.
그 날짜의 데이터를 다시 가져와서 옮기라고 말했다.
arbitrarily moving past date data would break consistency. 임의로 과거 날짜 데이터를 이동하면 일관성이 깨질 수 있다.
I learned that rather than just following instructions blindly,
I must double-check whether my work is correct
맹목적으로 따라하지 말고, 내가 하는 일이 잘 하는게 맞는지 재확인
To minimize risk, I created isolated test resources like a dedicated EMR cluster. 전용 EMR cluster 같이, 분리된 테스트 리소스를 생성했다
Once validated, I safely switched over  테스트가 마무리 된 이후 새로운 테이블을 기존 테이블로 안전하게 교체하였다
All team members wanted to switch directly to Spark 3 without testing  
This could lead to a dangerous situation where the entire operation halts 이는 전체 작업이 중단되는 위험한 상황으로 이어질 수 있다.
once I was assigned to handle WebUI processing using Spring.
I was assigned the task of adding functionality to display different screens based on user permissions
Spring을 사용한 WebUI 처리를 담당하도록 배정받았다.
사용자 권한에 따라 다른 화면을 표시하는 기능을 추가하는 작업을 맡게 되었다.
I conducted code reviews with team members to double-check for any shortcomings. 부족한 점이 없는지 다시 한번 확인했다.
I performed a staging deployment to verify that the screens displayed correctly for users with different permissions. 화면이 올바르게 표시되는지 확인하기 위해 스테이징 배포를 수행했다.
I received negative feedback regarding time management. 시간 관리에 대해 부정적인 피드백을 받았다.
I missed the deadline while waiting for approval and
received feedback that I failed to meet timelines.
승인을 기다리다 마감일을 놓쳤고
일정을 지키지 못했다는 피드백을 받았다.
I need approval to proceed with my work
I applied for approval in advance and requested it multiple times
but the response came late

업무 진행을 위해 승인이 필요하다.
사전에 승인을 신청하고 여러 차례 요청했다
하지만 답은 늦게 도착했다.
I will be comfortable working independently and handling tasks reliably.
독립적으로 업무를 수행하고 신뢰할 수 있게 업무를 처리하는 데 익숙해 질 것이다.
I want to participate in decisions about future direction and contribute to the team's future. 향후 방향에 관한 결정에 참여하고 팀의 미래에 기여하고 싶다.
My biggest strength is identifying inefficiencies in systems and improving them.
 
I’ve developed a strong habit of documentation and logging.
 
I'll share my thoughts along with the materials I researched and gathered beforehand.
사전에 조사하고 수집한 자료와 함께 내 생각을 공유할 것이다.
ROW_NUMBER() assigns a unique sequential number to each row, regardless of whether the values are the same.
 값이 같은지 아닌지 상관 없이
DENSE_RANK() assigns the same rank to rows with the same value, and the next rank is assigned without gaps. 다음은 갭 없이 랭크가 부여된다
RANK() assigns the same rank to rows with the same value, but it leaves gaps in the ranking sequence after ties. 같은 값을 갖는 랭크 이후 갭이 있다
Window functions are functions that preserve the context of the original data and do not reduce the number of rows after aggregation.  집계 후에 원본 데이터 맥락을 유지한다.
JOIN combines columns horizontally based on a condition, 
while UNION combines rows vertically and requires schema compatibility.
 
EXISTS ignores null values because it determines whether a row exists. (The existence of a row)
EXISTS 는 행 존재 여부를 판단하기 때문에 null 을 무시함
but I understand the concept and have worked on similar problems  
I’m not familiar with that term, so I don’t want to give an incorrect explanation.  
If it’s something I’ve encountered before under a different term, I’d be happy to explain from that perspective.
혹시 제가 알고있는 개념이라면 보충해서 이야기를 할 수 있을 것 같다
I haven’t worked with Streaming System yet, so I wouldn’t want to explain it inaccurately.
 
If your team uses Streaming System in production,
I’d make sure to study by watching online lectures,
understand how I can use and why it was chosen here,
and get hands-on experience 
so I can work with it safely in a production environment.
 
haven’t had hands-on experience with performance tuning yet. However, I have similar experience in terms of tuning.  
I can’t say for certain what the exact reasoning was.
정확한 이유가 무엇이었는지 단정할 수 없다.
However, based on my understanding of the system,
one possible reason could be cost efficiency in this part
하지만 제가 이해한 시스템 구조상 이 부분에서는 비용 효율성이 한 가지 이유가 될 수 있다
I didn’t design it myself, so I’d avoid making assumptions.  
The requester wanted data processed with the desired transformation
and wished to receive the data via SFTP according to a set schedule.
Throughout this process, the requester and I discussed how to handle duplicate data,
the final number of files, 
and how to notify us if issues occur.
요청자는 원하는 변환 방식으로 처리된 데이터를 원했으며,
정해진 일정에 따라 SFTP를 통해 데이터를 수신하기를 원했다.
이 과정 전반에 걸쳐 요청자와 저는 중복 데이터 처리 방법,
최종 파일 수, 문제 발생 시 통보 방식에 대해 논의했다.
We conducted many tests and
completed the work as the requester wanted.
As a result, I successfully built the data pipeline,
and the requester received the desired data.
우리는 여러 차례 테스트를 수행하고
요청자가 원하는 대로 작업을 완료했습니다.
그 결과, 데이터 파이프라인 구축에 성공했으며
요청자는 원하는 데이터를 수령했습니다.
Just retrieve the data for the date the issue was created  이슈를 만든 날짜의 데이터를 찾아라.
I proceeded with the task that way 그 방식으로 작업을 진행했다.
Therefore, arbitrarily moving past date data would break consistency.
따라서 과거 날짜 데이터를 임의로 이동하면 일관성이 깨질 것이다.
We only discovered this much later.
그제서야, 나중에야, 뒤늦게서야...(아쉬움)
S3 doesn't have the concept of directories.  s3 는 디렉토리 개념이 없다
Durability refers to the potential for data loss.
Durability refers to the likelihood of not lossing data.
Availability refers to the probability of being able to read data without issues.
Durability : 데이터를 잃어버릴 가능성. 99.999999999%
Availability : 데이터를 문제없이 읽을 수 있는 확률
We can use tags as indicators for distinguishing pusrposes when settling accounts later.
s3 bucket 에 tag 를 달면, 나중에 정산할 때 구분을 위한 지표로 사용 가능함
Glue Crawlers parse and infer from the csv file
Glue Crawlers 는 이 csv 파일의 정보를 분석하고 추론함
It remembers how far it previously collected data and
resumes collection from the point where it stopped.
이것은 이전에 데이터를 수집한 지점을 기억하고
중단된 지점부터 수집을 재개한다.
There are spaces before and after the name.
고객명 앞뒤 공백 있음
   
   

 

 

 

 

Spark 이론 정리 : 

https://eyeballs.tistory.com/m/206

 

 

Spark 질문은 원리 + 실무 판단력을 보기 위함

Spark UI 언급 = 실무 경험 신뢰도 급상승

모든 질문에 완벽할 필요 없음

왜 그렇게 했는지 설명할 수 있으면 충분

 

 

 

What is Apache Spark and why is it used?

Apache Spark is a distributed data processing framework designed for large-scale data processing. 
It provides in-memory computation, fault tolerance, and a high-level API, 
which makes batch and iterative workloads much faster compared to traditional MapReduce.

 

What is the difference between RDD and DataFrame?

RDD is a low-level API that provides fine-grained control but lacks automatic optimization. 
DataFrames are higher-level, schema-aware, and benefit from Catalyst Optimizer and Tungsten execution engine, 
so they are generally preferred for most workloads.


 

What is lazy evaluation in Spark?

Spark does not execute transformations immediately. 
Instead, it builds a logical execution plan and only triggers computation when an action is called, 
which allows Spark to optimize the execution plan.

 

What is the difference between transformation and action?

Transformations define how data should be processed and are lazily evaluated, 
while actions trigger the actual execution and return results or write data.

 

Explain Spark’s execution flow.

When an action is called, Spark creates a job, which is divided into stages based on shuffle boundaries. 
Each stage consists of tasks that are executed in parallel on executors.


 

What is a shuffle and why is it expensive?

A shuffle involves redistributing data across executors, usually during joins or aggregations. 
It is expensive because it requires disk I/O, network transfer, and serialization.


 

What causes shuffle in Spark?

Operations like groupBy, reduceByKey, join, distinct, and repartition can trigger shuffle 
because they require data to be reorganized across partitions.


 

How do you optimize joins in Spark?

I try to reduce shuffle by using broadcast joins when one dataset is small enough. 
I also ensure proper partitioning and avoid skewed join keys when possible.


 

What is data skew and how do you handle it?

Data skew occurs when a few keys dominate the data distribution, causing some tasks to take much longer. 
Common approaches include salting keys, filtering hot keys, or using broadcast joins.

 

What is partitioning and why is it important?

Partitioning determines how data is distributed across executors. 
Proper partitioning improves parallelism and resource utilization, 
while poor partitioning can lead to performance bottlenecks.


 

What is the difference between repartition and coalesce?

repartition increases or decreases partitions and triggers a shuffle, 
while coalesce typically reduces partitions without a full shuffle.


 

When would you cache or persist data?

I cache data when it is reused multiple times across different actions, especially if the computation is expensive.
I choose the storage level based on memory availability.

 

How does Spark handle failures?

Spark uses lineage information to recompute lost partitions. 
If a task or executor fails, Spark retries the task automatically on another executor.

 

Why is Parquet commonly used with Spark?

Parquet is a columnar storage format that supports compression and predicate pushdown, 
which reduces I/O and improves query performance.

 

How do you debug a slow Spark job?

I start by checking Spark UI to identify slow stages or skewed tasks, 
then review shuffle size, partition count, 
and executor utilization before applying optimizations.


 

Spark execution model 종류 및 차이
 

 

Spark execution flow (논리적 모델, 물리적 모델, stage, task 등)
 

 

partition, parallelism. input 파일 개수와 partition 의 관계?
 

 

join 종류와 어떤 상황에서 어떤 join 을 선택해야 하는지
 

 

executor 실패시 어떻게 되는지, 어떻게 복구할건지
 

 

skew 발생시 어떻게 대응할지
 

 

Why is this spark job slow? 느려지는 경우 어디서부터 어떻게 원인 찾고 해결할래?
 

 

How would you optimize it? 튜닝 방법
 

 

What are the RDD's in Spark?
 

 

Spark UI 에서 확인해야 하는 포인트
https://eyeballs.tistory.com/715

< Jobs Tab >


- 몇 개의 job이 실행되었는지
- 어떤 action이 job을 트리거했는지

하나의 action 이 하나의 job 을 만듦. 꼭 기억하자




< Stages Tab >

- Stage 실행 시간
- Shuffle Read / Write 크기
- Failed / Skipped stages

Stage 경계(boundary) 는 shuffle 기준으로 나뉨



< Tasks 상세 화면 >

- Task 실행 시간 분포
- 특정 task만 유난히 느린지 (skew 발생 여부 확인)
- Input size 차이

몇몇 task 가 특출나게 오래 실행된다면, skew 를 의심해볼 수 있음



< SQL Tab (DataFrame 사용 시) >

- Physical Plan
- BroadcastHashJoin 여부
- SortMergeJoin 사용 여부

물리적 실행 계획을 보고 어떤 join 전략이 사용되었는지 확인할 수 있음



< Storage Tab >

- 캐시된 DataFrame/RDD
- 메모리 사용량
- Storage Level



< Executors Tab >

- Executor 수

- CPU/Memory 사용률
- Shuffle Read/Write per executor
- GC time

각 노드의 리소스가 고르게 쓰이고있는지 확인 가능함



면접에서 다음과 같이 말하면 좋음

When a Spark job is slow, I usually start with the Spark UI, especially the Stages and Tasks tabs,
to identify shuffle-heavy stages or data skew.




 

 

 

 

 

 

 

 

 

Continue from below posting.

https://eyeballs.tistory.com/m/729

 

 

 

SQL 데이터베이스와 NoSQL 데이터베이스의 주요 차이점은?


구조: SQL 데이터베이스는 구조화된 스키마를 사용하는 반면, NoSQL 데이터베이스는 스키마가 없거나 유연한 스키마를 사용

확장성: SQL 데이터베이스는 scale-up 이 더 용이한 경우가 많고, NoSQL 데이터베이스는 일반적으로 scale-out 이 더 용이함


데이터 모델: SQL 데이터베이스는 테이블과 행을 사용하는 반면, NoSQL 데이터베이스는 document, Key-Value 또는 그래프와 같은 다양한 모델을 사용할 수 있음


ACID 준수: SQL 데이터베이스는 일반적으로 ACID를 보장하는 반면, NoSQL 데이터베이스는 성능 및 확장성을 위해 일부 ACID 속성을 희생할 수 있음





 

정규화와 비정규화 차이?

정규화 : 데이터 중복을 최소화하여 무결성을 높이는 과정
삽입,삭제,수정 이상(Anomaly)을 없애기 때문에, 무결성이 높아짐
join 쿼리가 필수이므로 쿼리 성능은 높지 않음
정규화를 진행하면, 테이블들을 최대한 나누고, 각 테이블들을 외래키를 통해 연결


비정규화 : 성능 향상을 위해 의도적으로 데이터를 중복시켜 조회 속도를 높이는 과정

비정규화를 진행하면, 테이블들을 최대한 결합



https://eyeballs.tistory.com/m/504




 

저장 프로시저(stored procedure)란?

저장 프로시저는 데이터베이스에 저장되고 한 번의 호출로 실행될 수 있는 미리 컴파일된 SQL 문 모음
매개변수를 받아 복잡한 연산을 수행하고 결과를 반환할 수 있어 성능 향상과 코드 재사용성 증대에 기여

마치 import 하여 사용할 수 있는 함수같음

https://eyeballs.tistory.com/m/504


 

람다 아키텍처란?


실시간으로 데이터 확인하기 위해 (결과는 부정확하지만) 데이터 스트림 처리를 하는 부분을 만들고
똑같은 데이터를 배치 데이터 플로우로 처리하여 나중에 일, 월 등의 긴 주기를 갖고 배치처리 한 결과를 정확한 결과로 보는 것
배치 처리 결과는 서빙레이어라는 부분에 모여서 사용자에게 서빙됨

배치 결과가 나오기 전까지, 스트리밍으로 처리된 결과는 참고용으로 볼 수 있음

람다 아키텍처의 단점은 같은 로직을 두 번 사용(스트림에서 한 번, 배치에서 또 한 번)한다는 것임


https://cazton.com/images/consulting/lambda-architecture/lambda-architecture-spark-hadoop-cazton.webp




람다를 대체하기 위해 카파 아키텍처를 선택할 수 있음

카파 아키텍처는 배치와 서빙 레이어를 완전히 없애고 스트리밍 부분만 남긴 것
kafka 에 데이터 쌓아두는 기간을 늘림
과거 데이터를 재처리하고 싶다면, kafka 로부터 다시 읽음

카파의 단점
 부하가 급격하게 높아질 수 있다는 것
예를 들어 재처리를 위해 과거 한달 데이터를 한 번에 보내면 스트리밍 처리에 부하가 높아질 수 있음



https://eyeballs.tistory.com/m/574
https://eyeballs.tistory.com/m/720




 

데이터 파이프라인에서 진행 가능한 테스트 방법들


- 개별 구성 요소에 대한 단위 테스트
- 구성 요소들이 서로 제대로 작동하는지 확인하기 위한 integrity 통합 테스트. 각 구성 요소들의 interface 가 잘 연결되는지 확인
- 전체 파이프라인에 대한 엔드투엔드 테스트
- 데이터 무결성을 보장하기 위한 데이터 유효성 검사 테스트
  - 무결성 테스트
  - 정합성 테스트
- 이슈 테스트
  - 다양한 부하 조건에서의 성능 테스트
  - 오류 처리 검증을 위한 오류 주입 테스트
- 변경 후 회귀 테스트




 

데이터 양이 갑자기 증가하는데 수직적, 수평적 증가가 불가능한 상황에서 데이터 양이 증가하면 어떻게 대응 할 것인가?
즉, 데이터 양은 증가하지만 추가 리소스를 사용할 수 없는 상황

스파크 리소스를 늘릴 수 없다면,
‘처리해야 할 데이터의 양’과 ‘재처리 범위’를 줄이고
‘파이프라인의 성격’을 바꿔야 함


파이프라인: MySQL → binlog (CDC) → Spark → Lakehouse
제약: 리소스를 더 추가할 수 없는 상황
목표: 데이터 파이프라인의 안정성을 유지하고, 작업 실패나 이슈 등 방지



핵심 질문은: “정말 10배 데이터를 ‘똑같이’ 처리해야 하는가?”

1. 가장 먼저 해야 할 것: CDC 범위 줄이기 (CDC 대상 컬럼 / 테이블 재검토)

MySQL 데이터가 10배 늘었다고 해서, 그 모든 데이터가 가치 있지 않을 수 있음

확인해야 할 질문:
  • 실제로 downstream(DS/BA)가 쓰는 테이블은?
  • 변경이 의미 있는 컬럼은?
  • audit / debug 용 데이터가 섞여 있지 않은가? -> 데이터 처리에서 제외시킬 수 있는 부분
대응
  • binlog 수집 대상 테이블 축소
  • CDC 제외 테이블 분리
  • 변경이 없는 테이블은 snapshot 주기 조정
즉, 꼭 필요한 데이터만 처리하도록 만듦
입력 데이터 자체를 줄이는 게 가장 큰 효과







2. Append-only + Incremental 처리 강제


여기서 append-only 란, 일단 append 로 저장하고 추후 재처리를 진행.


Hudi upsert 진행시, 덮어쓰기 위한 데이터를 찾는 과정에서
partition 을 찾을 수 없다면 full scan 이 발생하게 되므로 엄청난 오버헤드가 발생함
따라서, Hudi upsert 스캔에서 full scan 방지를 위해 반드시 partition pruning 되어야 함





Partition 전략 재설계 (필수)


❌ 잘못된 예:
partition = ingestion_date
➡️ 하루에 10배 → 하루 partition 하나 → hotspot


✅ 개선:
partition = event_date
or
partition = (event_date, hash(user_id))
👉 “한 배치가 건드리는 파일 수”를 줄이는 게 핵심

event_time 으로 파티셔닝하게되면, late-arriving data 처리는 (일단은) 생략되어 데이터양이 줄어듦
late-arriving data 는 나중에 다시 처리하면 됨








3. Spark 작업 자체를 가볍게 만들기


Spark executor 못 늘리면, executor가 할 일을 줄여야 함

Shuffle 최소화
  • broadcast join 가능하게 dimension 크기 제한
  • skew key 탐지 (user_id, order_id, Skew Join Hint 등)

Task 수 줄이기
  • 불필요한 repartition 제거
  • coalesce() 적극 사용

CDC 이벤트 정규화 (중요)

MySQL binlog는 종종:
  • update 하나 → multiple events
  • 같은 PK에 대한 잦은 변경

해결
  • Spark 이전 단계에서 collapse, 같은 PK + window 내 → 최신 1개만 유지
  • 예: key + max(updated_at)
➡️ 처리 데이터 수가 실제 변경 row 수로 줄어듦








4. “실시간에 가깝게”에서 “지연 허용”으로 전환



리소스 고정이면 선택지는 둘 중 하나:


1. Throughput 을 유지하는 걸 선택. 그럼 Latency 는 포기해야 함
2. Latency 를 유지하는 걸 선택. 그럼 데이터가 누락되거나 작업이 실패할 수 있음


따라서, 현실적으로 "지연 허용 + 안정성 유지"  를 선택해야 함


방법
  • micro-batch 크기 축소
  • backlog 누적 허용
  • SLA 재정의 (예: T+1 → T+2)




5. “절대 하면 안 되는 대응” (면접에서 말하면 감점)


“Spark executor 더 달라고 요청한다”
“지금은 어쩔 수 없다”
“하드웨어 증설이 답이다”


면접관이 듣고 싶은 말:

“리소스는 고정되어 있으니, 저는 파이프라인의 성격을 바꾸겠습니다.”






이 질문에서 면접관이 진짜 보고 싶은 것

- 데이터 엔지니어링 관점
- 시스템 트레이드오프 이해
- 현실적인 판단
- 리소스 제약 하 설계










데이터가 10배로 들어오는 상황에서 리소스를 늘릴 수 없을 때, 내가 생각한 방법

- 들어오는 데이터는 일단 모두 lake house 에 넣고, lakehouse 에서 한 번의 배치가 건드는 데이터 범위를 제한.
여기서 lake house 는 s3 처럼 무한한 저장 공간을 갖는다는 전제임


- 데이터 처리 병목 지점을 프로파일링해서 해결해야 함. 셔플 사이즈 이슈, IO 이슈 등이 발생할 가능성이 높음

- 데이터 처리하는 코드를 튜닝해야 함. 이를테면, 파티션 사이즈를 조절한다던지(AQE 등), 셔플을 최대한 줄일 수 있도록 broadcast join 을 활용한다던지(dimension table이 충분히 작아야 함), repartition 대신 coleasce 를 사용하고 groupbykey 대신 reducebykey 를 사용한다던지, skew 발생을 막기 위해 skew join hint 등을 사용한다던지. 물론 이것들은 '데이터양이 늘어났을 때 대책'이 아니라 일반적인 튜닝 방법임. 이걸 미리 해둬야 함


- 데이터양이 많아졌기 때문에, 읽는 데이터 양을 줄여야 함. 예를 들어, 데이터를 읽는 코드가 날짜 기준으로(날짜 파티셔닝 된 상태) 데이터를 읽는다면, 그 날짜 내 데이터를 모두 한 번에 읽는게 아니라 한 job이 스캔하는 파일 수 / 파티션 수를 제한해서 조금씩 읽고 처리하도록 만든다던가

하루치 데이터를 → 1시간 단위 / shard 단위 / hash bucket 단위로 쪼개서 → 여러 번 실행

- hudi 의 upsert 비용이 비싸기 때문에, 일단 append-only 로 데이터를 저장하고, 나중에 처리하는 것으로 진행. 이것은 throughput 은 지키되 latency 를 희생(DS/BA 가 사용 가능한 데이터는 나중에 생김)하는 방법.




 

데이터 파티셔닝의 개념과 분산 데이터 처리에서의 이점에 대해 설명해 주시겠습니까?

데이터 파티셔닝은 분산 시스템에서 데이터 세트를 더 작은 하위 집합 또는 파티션으로 나누어 여러 노드에 분산시키는 것을 말합니다.
이를 통해 데이터의 병렬 처리가 가능해져 자원을 효율적으로 활용하고 성능을 향상시킬 수 있습니다.

또한 파티셔닝은 데이터를 노드 전체에 고르게 분산시켜 부하 분산을 용이하게 하고, 핫스팟 발생을 방지하며 시스템 확장성을 개선합니다.

더 나아가 데이터 파티셔닝은 노드 장애가 전체 시스템에 미치는 영향을 최소화하여 내결함성을 강화합니다. ?? how??

일반적인 파티셔닝 전략으로는 특정 값 범위에 따라 데이터를 분할하는 범위 파티셔닝, 해시 값에 따라 데이터를 분산하는 해시 파티셔닝, 그리고 고유 식별자 또는 키에 따라 데이터를 분할하는 키 파티셔닝이 있습니다.



 

데이터 웨어하우스 환경에서 데이터의 최신성과 일관성을 어떻게 보장합니까?

최신성을 보장하려면 기준이 되는 날짜값 혹은 incremental value 가 있어야 할 것 같아. 이를테면 updated_date 를 기준으로 최신성을 판단하되, updated_date 가 동일하면 데이터가 생성될 때 받는 유니크한 incremental value 를 기준으로 최신성을 판단하면 좋을 것 같아. hudi 의 upsert 기능을 이용하면 편하겠지만, 사용할 수 없는 경우에는 직접 PK가 동일한 데이터끼리 updated_date+incremental value 를 통해 비교해서 가장 최신 데이터만 남기는 쪽으로 진행해야 할 것 같아.
여기서 일관성을 보장한다는 말은 integrity 를 말 하는 거겠지? integrity 를 보장하려면 hash 값, checksum 등을 만들어 비교해본다던가, 해당 컬럼값이 정상 범위인지 (not null 혹은 음수 체크 혹은 2301년 등의 이상한 미래값 등) 확인해본다던가, 소스DB 의 값과 비교해본다던가 할 것 같아.



⚠️ 보완하면 좋은 점
  1. 최신성과 일관성을 조금 섞어서 설명하고 있음
  2. “일관성 = integrity”만으로는 약간 좁음
  3. **운영 관점(재처리, 지연 데이터, 실패 복구)**가 빠져 있음
  4. “왜 그렇게 하는지”에 대한 이유를 조금 더 말하면 좋음



< 면접관이 의도한 개념 정리 >

최신성 (Freshness) : “가장 최신 상태의 데이터를 제공하고 있는가?”

핵심 질문:
- 최신 기준이 무엇인가?
- 늦게 도착한 데이터는 어떻게 처리하는가?
- 중복 실행해도 결과가 동일한가? (idempotency)
- 실패 시 재처리 가능한가?

  (재처리 시 중복이나 과거 데이터 overwrite는 안전한가)



일관성 (Consistency) : “데이터가 신뢰 가능한 상태인가?”

'일관성' 에 포함되는 의미들
- Schema consistency : 타입, 컬럼 구조
- Record-level consistency : PK 유일성, 최신 row
- Cross-table consistency : fact–dimension 관계
- Source-to-target consistency : 원본과 동일한 의미 (흔히 말하는 정합성)
- Temporal consistency : 시간 기준 정합성

integrity는 그중 일부일 뿐 (내가 볼 땐 4번 빼고 다 일관성임...)






< 추가하면 좋은 포인트들 >

  • late-arriving data 처리 : 늦게온 데이터가 갖는 PK 데이터의 updated_date + incremental value 가 최신이라면 덮어쓸것이고, 아니라면 무시될것임. late-arriving data 처리는 이미 완성되었지만, '언급'은 하는 게 좋겠음
  • event_time vs processing_time 구분
event_time 과 processing_time 구분해주면 좋음
event_time 을 기준으로 생성 순서를 알 수 있고,
재처리 할 때도 도움이 되고
event_time 으로만 집계 가능한 값, 이를테면 DAU(하루에 활동한 사용자 수) 집계에 도움이 됨
대신 late-arriving data 처리 등 추가 단계가 필요해서 "이제 한 번 사용해볼까?" 할 때는 processing_time 보다 느림(latency 가 있음)
(정확도를 위해 latency 를 희생함)

그럼 processing_time 은 언제 쓸까?
정확성은 높지 않지만, 빠른 집계 결과가 필요할때 사용함
(latency 를 위해 정확도를 희생함)





Hudi 못 쓸 때의 대안

ROW_NUMBER() OVER (
  PARTITION BY pk
  ORDER BY updated_date DESC, seq DESC
) = 1

이걸 "deterministic deduplication" 이라고 표현함







 

state-level idempotency 란? event-level idempotency 란? 


< State-level Idempotency >

같은 데이터를 여러 번 처리하더라도 최종 상태(state)가 변하지 않도록 보장하는 것

여러번 처리란, 재처리, 중복된 데이터 처리, 재시도 등을 의미함
배치 처리가 실패해서 재처리하거나,
백필하거나,
CDC 에서 중복 데이터가 들어왔거나....등등
결과적으론 다 같은 말 같지만... 아무튼 재처리 진행 후에도 테이블 상태는 동일해야 함



사용자 프로필 정보가 담긴 테이블을 만든다거나
계좌 잔액 정보가 담긴 테이블을 만든다거나
demension 테이블을 만드는 등
여러번 실행한 후에도 정보가 바뀌지 말아야 하는 테이블에서 사용됨

State-level Idempotency 는 주로 UPSERT / MERGE 기반 파이프라인으로 완성됨



예를 들어, user_id = 1 의 이름 변경 이벤트가 여러 번 들어옴

(user_id=1, name=Alice, updated_at=2024-01-01)

아래 쿼리를 통해 통합 진행

ROW_NUMBER() OVER (
  PARTITION BY pk
  ORDER BY updated_date DESC, seq DESC
) = 1

MERGE INTO users
USING updates
ON users.user_id = updates.user_id   -- 동일한 PK 기준
WHEN MATCHED AND updates.updated_at > users.updated_at   --최신 레코드만 남김
  THEN UPDATE SET ...


여기서 merge into 는,
'두 테이블을 비교해서 조건에 따라 insert, update, delete 를 수행'하는 명령어.
merge into = upsert 문법이라고 보면 됨
MySQL 에서 지원하지 않고, SparkSQL 에서는 지원함


MERGE INTO [target_table]  : 타겟 테이블
USING [source_table] : 소스 테이블
ON : 매칭 기준





SparkSQL 의 쿼리 예시

MERGE INTO users t
USING updates s
ON t.user_id = s.user_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *


MySQL 의 쿼리 예시

INSERT INTO users (...)
VALUES (...)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
updated_at = VALUES(updated_at);









< Event-level Idempotency >

같은 이벤트(event)가 여러 번 처리되더라도, 그 이벤트의 효과가 한 번만 반영되도록 보장하는 것


여기서 핵심은:
- event 단위
- side effect 방지



Append-only event log 에서 사용하거나,
스트리밍 / CDC / 로그 기반 파이프라인 에서 사용함
매출 집계해야하거나, 클릭수를 확인해야하는 상황에서 사용함

클릭수 집계해야하는데 재처리, 중복전송 등에 의해 동일한 이벤트를 여러번 처리하면
클릭수가 늘어나면 잘못된 집곗값을 볼 수 있음
따라서 event-level idempotency 가 필요한 것



event_id를 immutable PK로 사용
event log에서 dedup 을 반드시 진행해야 함


아래와 같은 쿼리를 사용하여 구현 가능함

WITH temp AS (
  *,
  SELECT ROW_NUMBER() OVER (PARTITION BY event_id ORDER BY ingestion_time) as rn
  FROM events
)
SELECT *
FROM temp
WHERE rn = 1;

여기서 ingestion_time 으로 정렬한 이유는,
같은 event_id 를 가지면 논리적으로 동일하 내용을 갖기 때문에
굳이 event_time 을 사용할 필요가 없어서(=late-arriving data 를 구분 할 필요가 없어서)






그래서 둘이 무슨 차이냐?

event-level idempotency 에서 다루는 데이터는 '이벤트 데이터'임
이벤트 데이터는 그 자체로 의미가 있음
클릭수+1 이벤트, 매출+100 이벤트 등
이 이벤트 데이터는 테이블에 들어가기 전에 deduplication 되어야 함
테이블에 중복 적용되는 순간 이슈가 됨

state-level idempotency 는 테이블 기준으로 멱등성을 제공함
테이블에 들어오는 로그들이 재처리되거나 중복 처리되어도
테이블 자체의 상태는 그대로여야 함

간단한 예로, event-level idempotency 는 보장되지 않지만 state-level idempotency 는 보장되는 경우를 생각해보자
동일한 eventId 를 갖는 매출+100 이벤트를 중복 발생하면
이게 테이블에서+100을 올리는 처리가 두 번 될 것임




실제 아키텍처는 아래와 같음


Event Log (append-only, event-level idempotency)
        
State Table (upsert, state-level idempotency)
        
DS / BA / API


안전한 이벤트 처리를 위해 이벤트 deduplication 이 필수






 

event-based 모델이란? state-based 모델이란?


< event-based 모델 >


생성되는 모든 이벤트를 append-only 로 table 에 추가하는 모델.
예를 들어, 수집하여 필터링한 이벤트들을 s3 에 그대로 차곡차곡 쌓는 것임
그리고 절대 건들지 않아야 함(=쌓은 데이터가 업데이트 되면 안 됨. immutable)

event-based 모델 데이터를 통해 히스토리가 정확하게 보존되기 때문에
신뢰 가능한 과거의 발자취를 기록하는 용도(로깅)로 사용되거나
혹은 이 기록들을 기반으로 재처리 진행하는 데 사용됨
혹은 감사(audit)용이나, 데이터 출처 보존 및 데이터 이해를 위해 사용됨

이건 마치 data lake 에 데이터를 쌓아두는 것과 비슷하군




< state-based 모델 >


히스토리 유지 없이, 오로지 현재 상태만 table 에 저장하는 모델 
새로운 데이터가 올 때마다 기존 데이터를 덮어쓰고 새로운 값을 유지함

저장 비용이 적음
쿼리가 단순하고 쿼리 성능이 좋음





그래서 이 둘은 각각 왜 언제 쓰이느냐?

event-based 모델은 source of truth 로 사용되고
state-based 모델은 serving layer 로 사용됨

간단하게, data lake, data lakehouse 가 사용하는 모델들이라고 보면 됨



실제 파이프라인은 아래와 같은 구조를 갖음

[Source DB / App]
        ↓
[Event-based Data Lake]
        ↓
[State-based Lakehouse]   ← MERGE / UPSERT
        ↓
[BI / DS / API]




 

데이터 파이프라인에서 오류가 아닌 이상치를 어떻게 감지 & 대응하는가?

여기서 말하는 '오류'는 파이프라인의 job 실패, mismatch 혹은 명백히 잘못된 데이터가 들어오는 경우(null PK 처럼)를 말함
'이상치'는 파이프라인의 정상 동작에 의해 생성되었지만, 기존 데이터의 분포, 패턴, 규모가 기대와 다른 경우를 말 함


예를 들어보자

- 데이터 볼륨 이상 : Volume Anomaly
평소에 100개 들어온 데이터가 오늘 갑자기 1만개 들어옴

- 값 분포 이상 : Distribution Anomaly
평균 30원 하던 물건이 갑자기 3000원이 됨

- 특정 값 이상
country="Kor" 로 답하는 비율이 30% 에서 99%가 됨

- 시간 관련 이상
event_time 이 미래시간임

- fact-dimension 테이블 간 관계가 깨진 경우
즉, fact table 에 존재하는 FK 가 dimension table 에 없는 경우





 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 

 

 
 
















Ref. 

- https://www.hipeople.io/interview-questions/data-engineer-interview-questions

- https://www.geeksforgeeks.org/data-engineering/data-engineer-interview-questions/

 

 

 

 

 

 

 

What is Apache Airflow? How is it most commonly used?

에어플로우는 Python 을 사용하여 정해진 시간/조건에 원하는 작업을 실행하도록 만들어주는 ETL 오케스트레이션 도구
에어플로우를 통해 어떤 작업이 언제 실행되는지 설정하여 데이터 파이프라인을 정의 할 수 있고
작업의 경과를 WebUI 로 모니터링 할 수 있어서
주기적으로 실행되어야 하는 작업들을 자동화하고 편하게 관리할 수 있음


Airflow is an ETL orchestration tool that uses Python. It triggers jobs at specific points in time.
We can monitor the process of the task via the WebUI.



 

What is a DAG and DagRun?

DAG 란 작업과 그 작업들 간의 관계를 나타내는 그래프임
명확한 시작점과 끝점이 있으며, 작업들 사이에 "순환"이 없음

airflow 에서 DAG 란 비순환 그래프를 이루는 데이터 파이프라인으로 이해할 수 있음
DAG 내에 여러 operators 를 설정하고 트리거하여 작업을 실행함
스케줄에 따라 무엇을 어떻게 실행할지 정의한 설계도
DAG 자체는 실행되지 않음. 그냥 스크립트임

DagRun 은 DAG 를 실제로 실행한 단위
(DagRun represents one execution of DAG)

DAG 가 여러번 실행되면 여러 DagRun 이 생성됨
각 DagRun 은 하나의 logical_date 를 갖음



 

What are the three parameters needed to define a DAG?

DAG 를 정의하기 위해 필요한 세 가지는 start_date, dag_id, 그리고 schedule

ID : DAG를 고유하게 식별하는 아이디이며 일반적으로 짧은 문자열로 설정함
start_date : DAG가 트리거되는 첫 번째 간격의 날짜 및 시간

schedule : DAG가 실행될 빈도. 매주, 매일, 매시간 또는 사용자 지정 값으로 설정. cron 표현식이나 @daily 등으로 설정 가능



ID is a unique value used to identify DagRun. It is typically composed of a short string.
start_date is the date and time of the first interval when the DAG is triggered.
schedule refers to the frequency at which the DAG will run.



 

What is an Airflow task and operator?
Whats the difference between them?

operatorDAG 에서 작업을 정의하는 템플릿
각 operator 마다 하나의 고유 작업을 설정할 수 있음
이를 테면, PythonOperator 는 python 코드를 실행하고
SparkSubmitOperator 는 spark 에 job 을 제출할 수 있음

Operator 가 작업을 정의한 템플릿이라면,
task 는 Operator 를 인스턴스화한 실행 단위임 (execution unit)
task_a = PythonOperator(...) 여기서 task_a 가 바로 task 임 (아직 실행된 거 아님)
마치 OOP 언어의 object 와 instance 의 관계같음

task instance 는 task 가 실행되면 생기는 실행 단위
예를 들어, 어떤 DAG 안에 3개의 Operator 가 존재하고 각각 task_a, task_b, task_c 를 설정했다고 하자
Scheduler 가 해당 DAG 를 실행하면 세 개의 task 들이 저마다 Task Instance 를 만듦
task instance 에는 메타데이터가 포함되어있음
(언제 실행되었고, task_id 는 무엇이고, logical_date 는 몇이고 누가 실행했고 어떻게 실행되었고... 등)
해당 정보는 Metastore 에 저장되며 WebUI 에서 task 상태 확인 가능



A task instance is an execution unit that is created when a task is executed.




from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime

def hello():
    print("hello")

with DAG(
    dag_id="example_dag",
    start_date=datetime(2024, 1, 1),
    schedule_interval="@daily",
    catchup=True
) as dag:

    t1 = PythonOperator(
        task_id="print_hello",
        python_callable=hello
    )


위와 같은 DAG 가 존재하고 이를 실행한다고 하자

Operator : 무슨 작업을 할 지 정의한 템플릿. 위 예제에서는 PythonOperator
task : Operator 의 인스턴스. 위 예제의 t1. 아직 실행된 거 아님

25년 6월 25일에 실행하면

DagRun : DAG 를 특정 시점(logical_date)에 실행한 기록. DAG 실행 1회를 의미함
DagRun 은 dag_id, logical_date(2025.06.24) 등을 갖음

task instance : task(위 예제의 t1)를 실행한 인스턴스. Operator 가 아닌 DAG 도 아닌 task 를 실행한 것임
이렇게 생성된 task instance 를  executor 가 worker 에게 전달하고
worker 들이 task instance 를 실행하게 됨
그리고 worker 가 실행한 결과는 task instance logic 에 의해 DB 에 저장됨









 

What are the core components of Airflow’s architecture?

Scheduler : 사용자가 정의한 DAG 를 주기마다 파싱, 분석한 'DAG 상태' 및 'DAG 메타데이터'를 metastore 에 넣음
(DAG 파일 자체는 .py 파일 그대로 존재함. metastore 에 저장되는 게 아님)
트리거 될 DAG 들을 확인하고 실행 가능하겠다 싶으면 실행하여 DagRun, task_instance 를 만든 후 Executor 에게 넘겨줌

Executor : Scheduler 가 작업을 실행하기 위한 전략
Scheduler 로부터 받은 실행 가능한 task_instance 들을 queue 에 넣고, worker 에 나눠져서 실행될 수 있도록 함
Local Executor, Celery Executor 등 어떤 방식으로 작업을 실행할지 결정함

WebServer : 사용자가 Airflow 와 소통하는 창구
설정된 값, DAG, task 의 상태를 모니터링 할 수 있고, 수동으로 DAG 를 trigger 할 수 있음

Metastore : airflow 의 DAG 및 task 상태 정보를 저장하는 저장소.
모든 컴포넌트가 DB 를 통해 상태 정보를 공유하기 때문에, single source of truth 라고 불림

worker 들은 queue 로부터 task instance 를 가져가서 실행함
내부 task instance login 에 의해, 실행한 task instance 의 상태나 결과가 metastore 에 기록됨
그래서 사용자가 WebUI 를 통해 확인 가능
(스케줄러가 worker 들의 결과 받아서 DB 에 저장하는 거 아님)


 

What are Task Groups? How are they used within DAGs?

task group 은 tasks 를 논리적으로 함께 묶어주는 역할을 함
사용자 입장에서 task 를 보기 편하게 구분할 수 있도록 도와줌
성격별로, 역할별로 task 를 그룹지어두면 이해하거나 설명할 때 편함



 

Given a data_interval_start and data_interval_end, when is a DAG executed?

data_interval_start 는 DAG 에 설정된 실행 주기(interval) 의 시작점이고
data_interval_end 는 DAG 에 설정된 실행 주기(interval) 의 끝점임
예를 들어, 매일 새벽 2시에 트리거되도록 스케줄링 된 DAG 의 interval 은 하루이며
2025년 6월 25일 새벽 2시에 트리거되었을 때
data_interval_start 는 25년 6월 24일 오전 2시,
data_interval_end 는 25년 6월 25일 오전 2시


 

What is the catchup parameter, and how does it impact the execution of an Airflow DAG?

catchup 파라미터를 true 로 설정하면, start_date 부터 logical_date 까지 scheduling 에 맞춰 실행됨(DagRun 생성)
만약 catchup 이 false 라면, DAG 를 active 했을 때 과거에 실행되지 않았던 날짜들은 무시하고, active 한 이후로만 트리거됨

마지막으로 실행한 날짜부터 오늘까지 아님. start_date 부터 오늘까지

The catchup parameter controls whether Airflow creates DAG runs for past scheduled intervals that were missed.

If catchup=True, when a DAG is enabled, the scheduler will create DagRuns for all past execution dates starting from the start_date up to the current date, based on the DAG’s schedule.

If catchup=False, the scheduler skips all past intervals and only creates a DagRun for the next upcoming schedule, meaning historical runs are not backfilled automatically.


This parameter is commonly set to False for streaming pipelines or non-idempotent jobs, and set to True when historical data processing is required.



 

What are XComs, and how are they typically used?

xcom 은 같은 DAG 내의 여러 tasks 간에 소량의 데이터를 공유하기 위한 기능
PythonOperator, BashOperator, Sensor... 등 다양한 operator 들을 통해 데이터를 공유할 수 있음

xcom 데이터는 key-value 형태로 metastore  에 저장됨
webui 에서 저장 가능

xcom 은 기본적으로 json-serializeable 한 값만 저장하는 것이 권장됨
대량의 데이터를 공유 할 때는 외부 storage 를 사용


 

What is idempotency? 
Why is this important to keep in mind when building Airflow DAGs?

멱등성이란, 여러번 실행해도 동일한 결과를 만드는 것을 말 함
airflow 에서 DAG 는 멱등성을 갖춰 작성되어야 함
airflow 작업이 실패하여 재실행 하거나, 두 번 이상 실행 될 수 있기 때문

catchup, backfill  등으로 과거 날짜 DagRun 을 다시 실행하게 되는 경우에도
동일한 결과를 출력해야 하기 때문에 멱등성을 중요함 
멱등성이 지켜지지 않으면 중복데이터 발생 가능



 

After writing a DAG, how can you test that DAG? Walk through the process from start to finish.

- pytest, unittest 등으로 PythonOperator 로직 테스트
- 각 task 가 정상 동작하는지 CLI 로 검사 : airflow tasks test my_dag my_task_id 2025-06-25
  scheduler, executor 없이 로컬에서 task 만 실행 가능함
- dag 가 정상 동작하는지 CLI 로 검사 : airflow dags test my_dag 2025-06-25
  dag 전체를 순서대로 실행 가능함
- test 환경의 airflow 에서 dag 를 실행해 봄


airflow tasks test CLI 로 테스트하면
scheduler, executor, worker 등이 관여하지 않음
의존성 상관 없이, 해당 task 하나만 로컬에서 (실제로) 실행해서 로직 이상 여부를 확인

airflow dags test CLI 로 테스트하면
scheduler, executor, worker 등이 관여하지 않음
dag 전체 구조 올바른지, task 의존성이 올바른지 확인



 

To manage credentials for connecting to tools such as databases, APIs, and SFTP sites, 
what functionality does Airflow provide?

'connections' 란, 외부 시스템에 접근하기 위한 접속 정보를 관리하는 기능
DB, APIs, S3, RestAPI, SFTP, Kafka 등

connections 에 접속 정보를 넣어두면, DAG 코드 안에서 password 등을 직접 넣지 않아도 됨

WebUI 를 통해 connections 관리 가능하며
connections 에 저장된 접속 정보는 metastore 에 저장됨

conn_id : 컨넥션 이름
conn_type : mysql, sftp, http 등
host : 서버 주소
schema : DB name, path 등
login : username
passowrd : password
port : port
extra : json 형태의 추가 설정


connections 에 저장된 정보를 사용 할 때는,
아래처럼 Hook 을 사용하여 conn_id 와 연결해주면 끝!

from airflow.providers.sftp.hooks.sftp import SFTPHook
from airflow.operators.python import PythonOperator

def download_file():
    hook = SFTPHook(ftp_conn_id="my_sftp_conn")
    hook.retrieve_file(
        remote_full_path="/remote/data.csv",
        local_full_path="/tmp/data.csv"
    )

task = PythonOperator(
    task_id="download_from_sftp",
    python_callable=download_file
)


다양한 Hook 이 있음
SFTPHook, MySqlHook, S3Hook....


추가로, connections 는 환경별로 다르게 관리 가능함
이를테면, dev, stage, prod 별로 다르게 설정 가능!





Airflow 에는 'Variables' 라는 기능도 있음

DAG, task 에서 참조할 수 있는 '전역 설정 값(key-value)' 저장소임
문자열, 숫자, json 등 저장 가능함.
Key-value 형태로 저장

connections 처럼 variables 도 WebUI 에서 설정하며,
환경별(dev, stage, prod)로 다르게 관리 가능함

주로 S3 버킷이름, 임계값(threshold), 파일 경로 등 고정적인 정보 저장용이며
비밀번호나 key 등의 민감한 저장을 위한 용도로 사용하지 않음

아래처럼 variable 을 불러와서 사용

from airflow.models import Variable

bucket = Variable.get("data_bucket")

def process():
    print(f"Reading data from {bucket}")

PythonOperator(
    task_id="process_data",
    python_callable=process
)



 

Your team is currently supporting a legacy data pipeline that leverages homegrown tooling. 
You’re tasked with migrating this pipeline to Airflow. How would you approach this?

- legacy data pipeline 은 블랙박스같은 느낌이 있기 때문에 조심해서 migration 해야 함. migration 하다가 로직이 달라질 수 있기 때문
- homegrown tooling 에 대한 코드, 문서, 기획서, 참고자료 등이 있는지 찾아봄
- source 와 target 을 구체적으로 정리
- 해당 파이프라인이 다른 외부 서비스를 사용하는지도 체크
- 내부 코드를 하나하나 검토하여 어떤 로직으로 이루어졌는지 확인하고 airflow 에서 구현 진행
- 모듈 별로 migration 진행
- source, target 과 연결시 필요한 인증 정보 등을 새로 만들어서 연결
- migration 진행중에 airflow 에서 제공하는 더 나은 기능(retry, alarm 등)이 있다면 추가
- migration 진행 과정을 문서로 정확하게 남겨서 추후 이슈 발생시 참고할 수 있도록 함
- 실제 두 파이프라인의 결과를 비교 테스트해봄. 한 달 정도 실제 데이터 기반으로 테스트해보고 , 잘 migration 되었다면 legacy 를 없애는 방향으로 진행


shadow run 이란?
feature flag, dual write 란?



 

Outside of traditional Data Engineering workflows, 
what are other ways that Apache Airflow is being used by data teams?
 







참고

 

https://www.datacamp.com/blog/top-airflow-interview-questions

 

+ Recent posts