개발 영어 공부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) throught 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

 

 

What’s the difference between INNER JOIN, LEFT JOIN, and FULL OUTER JOIN?

A, B 두 개의 테이블을 전제로 설명

Inner join : 두 테이블 A, B 모두에서 조인 조건이 일치하는 행만 반환. 매칭되지 않는 행은 양쪽 모두 제외됨.
A left join B : 왼쪽 테이블 A의 모든 행을 반환하고, B에서 매칭되는 값이 있으면 가져옴. 매칭이 안 되면 B 쪽 컬럼은 NULL로 채워짐
outer join : A, B 두 테이블의 모든 데이터를 반환. 매칭되지 않는 경우는 존재하는 쪽의 데이터 + 반대쪽 컬럼은 NULL로 반환

 

How would you find duplicate rows in a table? 

SELECT id, COUNT(*) AS cnt  -- id 가 이 만큼 중복되었다는 것을 같이 보여줌
FROM table
GROUP BY id
HAVING COUNT(*) > 1;


SELECT *
FROM table
WHERE id IN (
    SELECT id
    FROM table
    WHERE id IS NOT NULL
    GROUP BY id
    HAVING COUNT(*) > 1
);




SELECT t.*
FROM table t
JOIN (
    SELECT id
    FROM table
    GROUP BY id
    HAVING COUNT(*) > 1
) d
ON t.id = d.id;


 

Write a query to remove duplicate rows from a dataset.
How do you use ROW_NUMBER() to eliminate duplicates from a table?

delete 하는 것이 아니라, 중복된 데이터가 없는 결과를 추출

WITH ranking AS (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) AS rn
    FROM table
)
SELECT *
FROM ranking
WHERE rn = 1;


partition by 를 하여 생긴 그룹 내 레코드들끼리 row_number 를 만듦
다른 그룹에 영향을 주지 않음


 

 Write a query to get the second highest salary from an employee table.

with temp as (select *,
 dense_rank() over (order by salary desc) as rn
  from empoyee)

select *
from temp
where rn = 2

 

Explain the difference between RANK(), DENSE_RANK(), and ROW_NUMBER().

ROW_NUMBER() assigns a unique sequential number to each row, regardless of whether the values are the same.

Even if multiple rows have identical values, each row receives a different number.

DENSE_RANK() assigns the same rank to rows with the same value, and the next rank is assigned without gaps.

RANK() also assigns the same rank to rows with the same value, but it leaves gaps in the ranking sequence after ties.

When used with PARTITION BY, all three functions apply the ranking independently within each partition.


 

 

What are window functions, and when would you use them?

window functions 란, 집계 처리 이후에도 행 수가 줄어들지 않고, 원본 데이터의 맥락을 유지하는 함수
순위(rank), 누적합, Top-N per group 등을 집계할 때 사용


Window functions are functions that preserve the context of the original data and do not reduce the number of rows after aggregation.


 

Write a query to pivot a table without using PIVOT.






테이블의 행을 열로 바꾸는 것이 pivot 이고,
열을 행으로 바꾸는 것이 unpivot

위 두 테이블이 pivot 과 unpivot 한 상태임


SELECT product
 SUM(CASE WHEN region = 'US' THEN amount ELSE 0 END) as 'us_sales',
 SUM(CASE WHEN region = 'EU' THEN amount ELSE 0 END) as 'eu_sales',
 SUM(CASE WHEN region = 'ASIA' THEN amount ELSE 0 END) as 'asia_sales'
FROM table
GROUP BY product


SELECT product,
'US' as region,
us_sales as amount
FROM table
UNION ALL
SELECT product
'EU' as region,
eu_sales as amount
FROM table
UNION ALL
SELECT product
'ASIA' as region,
asia_sales as amount
FROM table



 

What does EXPLAIN or EXPLAIN ANALYZE do in SQL?

Explain : 쿼리가 어떻게 실행될지 설명하는 실행계획을 예측하여 보여줌 (쿼리 실행 안 함)

EXPLAIN
SELECT *
FROM orders
WHERE user_id = 123;


Explain Analyze : 실제 쿼리를 실행한 뒤 실행 계획과 성능 정보를 함께 제공

EXPLAIN ANALYZE
SELECT *
FROM orders
WHERE user_id = 123;


쿼리 성능 튜닝을 위해서 사용되거나,
인덱스 사용 여부 확인을 위해 사용됨


 

How would you optimize a slow-running SQL query with multiple joins?

join 이 많은 쿼리는 데이터 양, 조인 순서, 인덱스 여부 등을 확인하여 튜닝함

먼저 EXPLAIN 을 사용하여 실행 계획을 분석, 프로파일링 할 수 있음
full scan 여부, Join 방식(굳이 full outer 를 사용해야하나? 등) 등을 확인

join 진행시 불필요한 데이터가 포함되지 않게, 필요한 컬럼만 select 하도록 함
또한 where 조건을 사용하여 필요한 row 만 필터링 되도록 함
CTE, 서브쿼리로 데이터를 줄일 수 있다면 더욱 좋음

join 조건에 걸리는 컬럼에 인덱스를 추가
이외에도 group by, order by 등의 컬럼에도 인덱스 추가


  • Use indexes on frequently queried columns to speed up lookups.
  • Avoid SELECT * by specifying only the required columns.
  • Use joins wisely and avoid unnecessary ones.
  • Optimize using subqueries by replacing them with CTEs when appropriate.
  • Analyze query execution plans to identify bottlenecks. Example:



 

What's the difference between HAVING and WHERE?

where 는 일반적인 쿼리문에서 값을 필터링하는 조건문
having 은 group by 로 묶인 데이터 번들을 필터링하는 조건문


 

What’s the best way to calculate a moving average in SQL?
Write a query to calculate the rolling average of sales for the past 7 days.

rolling, moving window 란, 시간에 따라 계속 슬라이딩되면서 계산되는 집계 방식
지금 시점 기준으로, 일정 기간의 데이터만 계속 잘라서
그 구간 안에서 합계, 평균, 최댓값 등을 계산하는 기법임

SELECT
    date,
    visitors,
    AVG(visitors) OVER (
        ORDER BY date
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) AS moving_avg_7d
FROM daily_visitors;

여기서 rows between 6 preceding and current row 는
현재 row를 포함하여 7개의 row 만 집계하라는 뜻을 갖음



또 다른 예
마지막 7일간 신규 주문 수

SELECT
    order_date,
    COUNT(*) OVER (
        ORDER BY order_date
        RANGE BETWEEN INTERVAL '6 days' PRECEDING AND CURRENT DATE
    ) AS rolling_7d_order_count
FROM orders;


 

Write a query to find the top 3 customers by revenue in each region.

with top as (select *,
dense_rank() over (partition by region order by revenue desc) as ds
from table)

select *
from top
where ds <= 3

 

How do CTEs (Common Table Expressions) help in writing better SQL?

Common Table Expressions 는 with as 명령어로 만들어진 임시 테이블을 말 함
사람이 읽기에 보기 좋고(readability 향상), 작성 의도 파악이 쉽고, 동일한 로직을 중복 작성하지 않도록 도와줌
윈도우 함수를 사용할 때 자주 사용됨

서브쿼리와 동일한 퍼포먼스를 보이기 때문에
서브쿼리와 비교하여 성능적 향상은 없음


 

What is a correlated subquery, and how is it different from a regular subquery? 

regular subquery : (서브쿼리를 감싸는) 바깥 쿼리와 독립적으로 실행되는 서브쿼리
바깥 쿼리의 컬럼을 참조하지 않으며, 서브쿼리는 단 한 번만 실행

correlated subquery : (서브쿼리를 감싸는) 바깥 쿼리의 컬럼을 참조하는 서브쿼리
outer query 없이 실행이 불가....
outer query 의 각 row 마다 서브 쿼리가 반복 실행(!)
그래서 performance overhead 가 생길 수 있음

예를 들어,

SELECT e.name, e.department, e.salary
FROM employees e
WHERE e.salary > (
    SELECT AVG(salary)
    FROM employees
    WHERE department = e.department
);

employees 의 각 row 마다 반복적으로 서브쿼리가 실행됨.....


 

How would you compare performance between a JOIN and a UNION?

JOIN combines columns horizontally based on a condition, 
while UNION combines rows vertically and requires schema compatibility.

JOIN and UNION serve different purposes, so can't compare them.


 

What is DDL and DML?

DDL : Data Definition Language


CREATE DATABASE mydatabase;
CREATE TABLE mytable;
CREATE VIEW myview;
CREATE INDEX myindex ON mytable (mycolumn);

ALTER TABLE mytable ADD mycolumn string;
ALTER TABLE mytable MODIFY mycolumn string;
ALTER TABLE mytable DROP COLUMN mycolumn;
ALTER TABLE mytable RENAME TO mynewtable;

DROP DATABASE mydatabase;
DROP TABLE mytable;


DML : Data Manipulation Language


INSERT INTO mytable (name, sex) VALUES ('eyeballs', 'male');

SELECT * FROM mytable WHERE name = 'eyeballs';

UPDATE mytable SET name = 'eyeballs', age = 20 WHERE sex = 'male';

DELETE FROM mytable WHERE name = 'eyeballs';
 


 

What’s the difference between DELETE, TRUNCATE, and DROP?

delete 는 조건에 맞는 레코드(row)를 삭제하는 명령어
로그가 많이 남기 때문에 상대적으로 느림

truncate 는 테이블의 모든 row 삭제하는 명령어 (row 만 삭제하고 테이블은 그대로 존재)
delete 와 다르게 where 를 사용할 수 없음
로그가 거의 남지 않아 delete 보다 빠름

drop 은 테이블, 데이터베이스 등을 삭제하는 명령어


 

How do indexes improve performance? When might they hurt it?

index 가 적용된 컬럼으로 쿼리를 실행하면 전체 검색을 하지 않고도 찾을 수 있어서 검색 효율이 굉장히 좋아짐
하지만 indexing 된 컬럼의 정보를 저장해야하므로 storage space 를 소모하며
데이터 수정 작업 (insert, update, delete) 퍼포먼스에 악영향을 줌


 

How can you rank users based on their total purchase value in descending order?

WITH user_totals AS (
    SELECT
        user_id,
        SUM(purchase_amount) AS total_purchase
    FROM purchases
    GROUP BY user_id
)
SELECT
    user_id,
    total_purchase,
    RANK() OVER (ORDER BY total_purchase DESC) AS user_rank
FROM user_totals;


 

Explain the concept of CASE statements with an example.

select CASE 

  WHEN score >=90 THEN 'A',
  WHEN score >= 80 THEN 'B'
  ELSE 'C'
END as grade

 

Write a query to count the number of unique users by day.


SELECT
    DATE(event_time) AS event_date,
    COUNT(DISTINCT user_id) AS unique_users
FROM user_events
GROUP BY DATE(event_time)  
ORDER BY event_date;

 

How would you calculate a cumulative sum of a column?

SELECT *,
    SUM(amount) OVER (ORDER BY date) AS acc
FROM table;


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

 

Write a query to identify the first and last transaction of each user.


with first_last as (
select
user,
rank() over (partition by user order by date asc) as first,
rank() over (partition by user order by date desc) as last
from table
)

select user
from first_last
where first = 1 or last = 1

 

How would you handle missing values in SQL?

missing values 은 주로 null 을 의미하는데
여기서 null 값을 어떻게 처리하느냐는 비즈니스 의미, 목적에 따라 달라짐

대부분의 집계 함수(sum, avg, count) 는 기본적으로 null 값을 자동으로 제외함

- null 값을 다른 값, 예를 들어 '' 혹은 0 등으로 대체할 수 있음 (select coalesce(c, 0) as c from table)
- null 값을 갖는 레코드를 무시할 수 있음 (where c is null)
- case when 을 사용하여 null 값이 오면 다르게 처리 할 수 있음
- count(col) 은 null 을 제외하지만, count(*) 은 null 을 포함하므로 null 차이를 눈으로 확인 가능


Removal: Simply remove rows or columns with missing data if they are not significant
Imputation: Fill missing values with statistical measures (mean, median) or use more sophisticated methods like KNN imputation.
Indicator variable: Add an indicator variable to specify which values were missing
Model-based imputation: Use predictive modeling to estimate missing values

Handling missing data is essential for maintaining data integrity. Common approaches include:
  • Using COALESCE(): This function returns the first non-null value in the list.
  • Using CASE statements: To handle missing values conditionally.



 

how would you clean a dataset with inconsistent formats (e.g., date or string issues)

포맷이 어긋난 데이터의 포맷을 맞추는 작업


날짜의 경우

SELECT
    CAST(date_string AS DATE) AS standardized_date
FROM raw_data;

SELECT
    DATE_PARSE(date_string, '%Y/%m/%d') AS standardized_date
FROM raw_data;


문자열의 경우

SELECT
    UPPER(TRIM(name)) AS clean_name
FROM users;


 

Write a query to calculate the time difference between consecutive events for each user.

SELECT
    user_id,
    event_time,
    event_time - LAG(event_time) OVER (PARTITION BY user_id ORDER BY event_time ) AS time_diff
FROM user_events
ORDER BY user_id, event_time;


여기서 event_time - LAG(event_time) 에서 사용되는 lag 는 
행 단위로 계산하는 윈도우함수이기 때문에
앞의 event_time 을 따로 정렬하지 않아도
알아서 lag 의도대로 계산됨


 

Can you create a simple temporary function and use it in an SQL query?

CREATE TEMPORARY FUNCTION get_gender(type VARCHAR) RETURNS VARCHAR AS (
  CASE 
    WHEN type = "M" THEN "male"
    WHEN type = "F" THEN "female"
    ELSE "n/a"
  END
);
SELECT
  name,
  get_gender(type) AS gender
FROM class;


 

How do you add subtotals in SQL?

Adding subtotals can be achieved using the GROUP BY and ROLLUP() functions

SELECT
  department,
  product,
  SUM(sales) AS total_sales
FROM sales_data
GROUP BY ROLLUP(department, product);

 

두 쿼리의 결과 차이?
SELECT * FROM A WHERE col IN (SELECT col FROM B);
SELECT * FROM A WHERE col IN (SELECT DISTINCT col FROM B);

distinct 상관 없이 in 이 있기 때문에 결과는 같을 것
가능하다면, IN 보다 EXISTS 를 사용하는 편이 좋다고 함. 성능적인 면에서, null 영향을 피하는 면에서


참고로 WHERE col IN (null) 에서 where 의 결과는 unknown 이기 때문에 false 가 되어 모든 결과값이 없는 결론
(where 는 true 값만 필터링함. false 나 unknown 은 통과시키지 않음)
설령 col 에 null 이 포함되어 있어도 (null IN (null)) 결과는 false가 됨
null 은 비교 불가능한 상태이기 때문

null 을 찾으려면 col is null 을 사용해야 함



 

IN 과 exists 의 null 처리 방식

where num IN(2, null) : num = 2 or num = null
num 이 2라면 true 가 나오지만, null도 역시 비교가 됨
null과 비교한 결과는 unknown이 나오는데
이것 때문에 "num IN(2, null)" 자체가 unknown 이 되어버림
where unknown 은 false 로 처리됨



where num NOT IN(2, null) : num !=2 and num != null
위 이유와 동일하게 num != null 때문에 unknown이 발생하며
"num NOT IN(2,null)" 자체가 unknown 이 되어버림


따라서, in 을 사용 할 때는 null 값을 미리 제거하고 사용해야 함
where num IN(select n from t where n is not null)



SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);

위와 같이 EXISTS 는 행 존재 여부를 판단하기 때문에 null 을 무시함
in 처럼 null 을 미리 처리하지 않아도 괜찮음



 

다음 쿼리가 느린 이유를 설명하고, 어떻게 튜닝하겠는가? 컬럼에 연산을 하면 index 타지 않는다는 것이 힌트
SELECT * FROM orders WHERE amount * 1.1 > 100;

인덱스는 컬럼의 원본 값을 기준으로 구성되어있기 때문에
amount*1.1 처럼 연산을 추가하면 인덱스를 사용할 수 없어서 full scan 이 발생함

따라서 컬럼을 그대로 사용할 수 있도록 연산을 이동하는 등의 작업이 필요

SELECT * FROM orders WHERE amount > 100 / 1.1;


 

covering index란 무엇인가? 언제 사용하면 좋은가?

covering index 란, 쿼리에서 필요한 모든 컬럼을 인덱스만으로 처리할 수 있는 인덱스를 의미함
즉, 테이블 접근 없이! 인덱스 내 데이터만 스캔(사용)하여 쿼리할 수 있음

아래처럼 index 를 만든 상황에서

CREATE INDEX idx_orders_customer_cover
ON orders (customer_id, order_id, amount);

아래 쿼리를 실행하면 인덱스만 가져와서 결과를 도출할 수 있음

SELECT order_id, amount
FROM orders
WHERE customer_id = 10;


자주 실행되는 조회 쿼리, 읽기 비중이 높은 테이블, 네트워크 IO 가 병목인 경우에 사용하면 좋음
그러니까 covering index 이 될 수 있도록 필요한 컬럼들에 index 을 추가한다는 말이구나


 

COUNT(*)와 COUNT(column)의 차이? 인덱스 영향을 받는가?

count(*) 은 null 까지 포함하여 계산
count(column) 은 null 을 제외하여 계산

인덱스가 존재하면, 테이블 대신 인덱스를 스캔하여 더 빠르게 쿼리할 수 있음


 

고객 테이블과 주문 테이블이 있을 때, ‘한 번도 주문하지 않은 고객’을 찾는 SQL을 작성하라

select c.name
from orders o
right join customers c
on o.name = c.name
where o.name is null


select name
from customers
where name not in (select distinct name from orders)


 

유저별로 첫 구매(first purchase)를 찾는 SQL

select id, min(date)
from users
group by id



row_number() over(partitioned by id order by date)

 

중복 이메일을 가진 유저를 모두 찾는 SQL

select email, count(1)
from users
group by email
having count(1)>1


 

파티션된 테이블(year, month, day)에서 최근 하루 데이터를 가져오는 SQL을 작성하라

SELECT *
FROM events
WHERE (year, month, day) = (
    SELECT year, month, day
    FROM events
    ORDER BY year DESC, month DESC, day DESC
    LIMIT 1
);


where (a,b,c) = (a, b, c) 이런식으로 조건비교가 가능하구나


 

event 로그에서 ‘DAU (Daily Active User)’ 구하는 SQL


select
date(dt),
count(distinct(userid))
from table
group by date(dt)


 

지난 7일간 유저별 session 수 계산

select
  user_id,
  count(*) as session_count
from table
where session_date >= CURRENT_DATE - INTERVAL '7' DAY
group by user_id;


 

로그 테이블에서 이벤트 A 이후 5분 안에 이벤트 B를 발생시킨 유저 수 구하기

SELECT COUNT(DISTINCT a.user_id) AS user_cnt
FROM event_logs a
JOIN event_logs b
  ON a.user_id = b.user_id
 AND a.event_type = 'A'
 AND b.event_type = 'B'
 AND b.event_time BETWEEN a.event_time AND a.event_time + INTERVAL '5' MINUTE;



 

CHAR, VARCHAR 차이는?

CHAR 는 고정 길이
VARCHAR 는 가변 길이를 사용하기 때문에
길이가 고정되어 있는 문자열을 표현할 때 CHAR,
길이가 불규칙한 문자열을 표현할 때 VARCHAR 사용

CHAR 에서 부족한 길이는 공백으로 패딩하지만(공간 낭비)
VARCHAR 에서는 부족한 공간이 없음

CHAR 는 길이가 고정되어있으므로 쿼리 실행이 안정적이고 빠름
VARCHAR길이가 고정되어있지 않아 쿼리 실행시 캐스팅 등의 추가 비용이 발생


 

VARCHAR(max) 사용 시 문제점은?

varchar(max) 는 full index 생성이 불가하여 검색 성능이 떨어짐
내부 비교 연산 진행시, varchar(max) 에 담긴 데이터를 캐스팅하는 추가 작업이 있어서 오버헤드로 작용한다고 함



S3에서 Parquet과 ORC의 차이? 언제 사용?

둘 다 columnar storage format 이라
컬럼 읽기에 특화되어 있고, 압축 효율이 좋으며 공간 차지도 덜 함

Parquet 은 Spark, Hive, Athena, Presto, Redshift 등과의 호환성이 대단히 좋음
업계 표준
Nested data 구조(json) 를 지원함
Spark, Athena, Glue ETL 등의 기본 선택 포맷임

Orc 는 Hive 기반 시스템에 최적화 되어있음 (presto, Tez)
따라서 Hive 를 사용할 때 선택하는 포맷임
parquet 보다 압축률이 좋음


 

Redshift Spectrum (External Table) 의 장단점은?

Spectrum 은 s3 에 있는 데이터를 external table 형태로 직접 쿼리하는 기능

s3 는 무한대로 확장 가능하여 저장 공간 이슈가 없음
spectrum 작업 자체는 redshift 가 아닌 외부(s3) 애서 처리되기 때문에 클러스터 성능에 영향을 덜 줌
무슨 말이냐면, redshift 클러스터의 compute node 가 s3 데이터를 읽는 게 아니고
redshift 외부의 별도로 존재하는 spectrum worker 인프라가 s3 데이터를 읽고 처리한다는 말
(s3 -> redshift compute node 로 직접 들어오는 게 아니라
s3 -> spectrum worker(serverless) -> redshift 로 들어옴)
외부 spectrum workers 는 s3 데이터를 읽고, 프루닝하고 , 필터링하고, 프로젝션하는 등의 전처리 과정을 진행하고
결과만 redshift 로 보내어 compute nodes 가 작업할 수 있도록 도와줌


spectrum 사용시, Glue Data Catalog 를 재사용 가능

하지만 S3 에서 읽어와야 하는 만큼 네트워크 IO 오버헤드가 발생
DML(update, delete 등) 의 기능이 거의 없음


 

WHERE col = NULL이 왜 작동하지 않는가?

NULL 비교는 IS NULL 사용해야 하기 때문

 

DISTINCT 와 GROUP BY 중 어느 게 더 빠른가? 이유는?

distinct 가 더 빠름
distinct 는 중복 제거만 수행하지만
groupby 는 중복 제거에 집계 준비 과정까지 진행하기 때문 (집계 함수 수행을 위한 구조를 생성해 두는 작업)




 

실수를 표현하는 세 가지 타입

decimal : 높은 정확성, 낮은 처리 속도. 정밀한 숫자 계산에 필요. 주로 돈 정보를 넣는다고 함.
double : 실수를 표현할 때 일반적으로 사용함.
float : 낮은 정확성, 높은 처리 속도


 

날짜를 표현하는 세 가지 타입

date : 날짜 정보만 표현
datetime : 날짜 + 시간 정보 표현
timestamp : 날짜 + 시간 + timezone 표현. 주로 timestamp 를 많이 사용함


 

count(1) 과 count(*) 의 차이

성능 차이는 없음
많은 DB 에서 count(*) 실행 성능 최적화가 되었기 때문


 

Min 과 Order By limit 1 의 차이
https://eyeballs.tistory.com/m/463

 

SELECT 1 vs SELECT TRUE

select 1 은 int 리터럴, select true 는 boolean 리터럴을 반환함

둘 다 exists 서브쿼리에서 사용 가능함


 

 

https://www.linkedin.com/posts/christopher-garzon-647081101_20-sql-interview-questions-for-data-engineers-activity-7322970317293772800-1luY/

https://medium.com/@krthiak/sql-interview-questions-day-95-of-100-days-of-data-engineering-ai-and-azure-challenge-6984530f7868

 

 

 

 

+ Recent posts