Data Engineering & Cloud Platforms

Interview Context

資深 DS 面試常會測試你對「資料從哪裡來、怎麼流到你手上」的理解 — 你不需要會維運 Kafka cluster,但要能講清楚 data lake 和 warehouse 的差異、什麼時候用 Spark、pipeline 掛掉時去哪裡找問題。這些題目篩掉的是「只會在 notebook 裡等別人餵資料」的候選人。

What You Should Understand

  • 能畫出一個 modern data platform 的分層架構:sources → ingestion → storage → processing → serving
  • 能比較 data lake、data warehouse、lakehouse,並解釋 medallion architecture 和 table formats(Delta / Iceberg / Hudi)
  • 知道為什麼 Parquet 是分析工作的預設格式,以及 partitioning 和 predicate pushdown 怎麼省錢
  • 能解釋 ETL vs ELT、Airflow DAG 的 idempotency 和 backfill、dbt 的角色
  • 理解 Spark 的 driver/executor 模型、shuffle 的成本,並能判斷什麼時候 pandas 就夠了
  • 能把 storage / warehouse / processing / streaming / orchestration 對應到 AWS、GCP、Azure 的服務

The Modern Data Platform Landscape

A modern data platform moves data through five logical layers:

OLTP SourcesIngestionStorageProcessingServing (BI / ML)\text{OLTP Sources} \to \text{Ingestion} \to \text{Storage} \to \text{Processing} \to \text{Serving (BI / ML)}
LayerWhat HappensExample Technologies
SourcesOperational systems generate dataPostgreSQL, MySQL (OLTP), app events, third-party APIs, logs
IngestionMove data into the platformKafka / Kinesis (streaming), Fivetran / Airbyte (batch CDC), SDK event trackers
StorageDurable, cheap, scalable landing zoneS3 / GCS / Azure Blob (data lake), warehouse native storage
ProcessingClean, join, aggregate, feature-engineerSpark, dbt + warehouse SQL, Flink (streaming)
ServingExpose data to consumersWarehouse (BI dashboards), feature store (ML), reverse ETL (back to apps)

直覺:OLTP database 是為了「快速處理單筆交易」設計的(row-oriented、高併發、低延遲),分析查詢卻是「掃很多 rows、只看幾個 columns」— 直接在 production DB 上跑分析會拖垮線上服務,所以要先把資料複製到專為分析設計的系統。這就是整個 data platform 存在的理由。

Who Does What

RoleOwnsTypical ToolsCares About
Data EngineerIngestion, storage, pipeline infrastructureKafka, Spark, Airflow, TerraformReliability, throughput, cost
Analytics EngineerTransform layer, curated tables, metric definitionsdbt, SQL, warehouseData modeling, correctness, documentation
Data ScientistAnalysis, experiments, models built on curated dataSQL, pandas, Spark, feature storeStatistical validity, feature quality

Where a DS touches each layer:

LayerDS Involvement
Sources / Ingestion定義需要哪些 events 和 fields(event taxonomy)— 沒 log 到的資料永遠拿不回來
Storage直接讀 lake 上的 raw data 做 exploration,理解 partitioning 才不會掃全表
Processing寫 feature pipeline、把 ad-hoc notebook 邏輯 production 化
Serving主要消費者 — 定義 metrics tables、訓練資料集、監控報表

為什麼 DS 面試考這個

面試官想確認你能和 data engineer 有效協作:你提的需求是否合理(「我要每 5 分鐘更新的全量 join」成本極高)、pipeline 出問題時你能不能自己 debug 到一半(查 partition 是否 late、上游 schema 是否變了),而不是每次都開 ticket 等人救。

Data Lake vs Data Warehouse vs Lakehouse

Data warehouse: a system that stores structured, schema-enforced data optimized for SQL analytics (schema-on-write). Data lake: a repository of raw files in open formats on cheap object storage, interpreted at read time (schema-on-read). Lakehouse: data lake storage plus a transactional table format layer, giving warehouse-like guarantees on lake economics.

DimensionData WarehouseData LakeLakehouse
SchemaSchema-on-write(寫入時強制)Schema-on-read(讀取時才解釋)Schema enforcement + evolution
Data typesStructuredStructured + semi/unstructured (logs, images, JSON)Both
Storage costHigher (proprietary format, coupled compute)Very low (object storage)Very low (object storage)
Governance / qualityStrong (constraints, ACLs)Weak by default(容易變 data swamp)Strong (ACID, schema checks, time travel)
Query performanceExcellent (optimized engine)Depends on file layoutNear-warehouse with good layout
Best forBI, curated metrics, finance reportingRaw event archive, ML training data, explorationSingle platform for BI + ML
ExamplesBigQuery, Redshift, SnowflakeS3 + Parquet, GCS + AvroDatabricks + Delta Lake, Iceberg on S3

直覺比喻:warehouse 像整理好的圖書館(上架前先分類編目,找書很快);data lake 像倉庫(什麼都先丟進去,便宜但要找東西時得自己翻);lakehouse 是在倉庫裡加上圖書館的目錄系統 — 保留便宜的儲存,補上交易保證和治理。

Medallion Architecture

Lakehouse pipelines are commonly organized into three quality tiers:

TierContentTransformationsConsumers
BronzeRaw data, as ingested, append-onlyNone(只加 metadata:ingest time, source)Data engineers, reprocessing
SilverCleaned, deduplicated, typed, joinedFiltering, dedup, schema conformanceDS exploration, feature pipelines
GoldBusiness-level aggregates, metrics tablesAggregation, business logicBI dashboards, ML training sets, execs

直覺:Bronze 保留「事實的原始證據」讓你永遠可以重算;Silver 是「可信的明細」;Gold 是「可以直接給老闆看的數字」。錯誤修復的原則是往上游修 — 如果 Gold 的數字錯了,修 Silver 的邏輯再重跑,而不是手動改 Gold。

Table Formats: Delta Lake / Iceberg / Hudi

Plain Parquet files on S3 have no transaction log — concurrent writes can corrupt each other, and there is no way to update or delete rows safely. Table formats add a metadata layer that provides:

CapabilityWhat It MeansWhy DS Cares
ACID transactionsConcurrent read/write without corruptionPipeline 寫到一半失敗不會留下半套資料
Time travelQuery the table as of a past version/timestamp重現「上週訓練時看到的資料」— reproducibility
Schema evolutionAdd/rename columns without rewriting all files上游加欄位不會弄壞舊查詢
Upserts / deletesMERGE INTO on object storageGDPR deletion, CDC 同步, SCD 維護
Compaction / clusteringRewrite small files into large ones避免 small-file problem 拖慢查詢
FormatOriginDistinguishing Trait
Delta LakeDatabricksTightest Spark/Databricks integration, simple JSON transaction log
Apache IcebergNetflixEngine-agnostic (Spark, Trino, Flink, Snowflake, BigQuery 都支援), hidden partitioning
Apache HudiUber專攻 upsert-heavy / CDC ingestion workloads

Time Travel 和 ML Reproducibility

面試常見追問:「你的 model 三個月前訓練的,現在要 debug,怎麼拿到當時的訓練資料?」標準答案就是 table format 的 time travel(查詢特定 version / timestamp 的 snapshot),搭配把 data version 記錄在 model registry 的 metadata 裡 — 這連回 ML pipelines 那頁的 data versioning 主題。

Object Storage Foundations

Why S3-style object storage underpins nearly every data lake:

PropertyDetailConsequence
DurabilityObjects replicated across devices and availability zones (S3 advertises 99.999999999% durability)幾乎不用擔心資料遺失
Elastic capacityNo provisioning — store bytes, pay per GB-month不用預估容量
Cheap tiersStandard → Infrequent Access → Glacier冷資料成本可以再降一個數量級
Decoupled compute/storageAny engine (Spark, Trino, DuckDB) reads the same files換 query engine 不用搬資料;沒人查詢時 storage 幾乎不花錢
Flat namespaceObjects addressed by key; "folders" are just key prefixesImmutable objects — 修改 = 重寫整個 object,所以適合 append 型 workload

和傳統 HDFS 或 warehouse 綁定的儲存相比,decoupled compute/storage 是雲端資料架構最核心的轉變:compute 可以隨用隨開隨關,storage 永遠在線且便宜。

Partitioning

Data lake tables are laid out as directory prefixes, e.g. events/dt=2026-07-01/country=TW/part-0001.parquet. Query engines use these prefixes to prune irrelevant files:

  • 查詢帶 WHERE dt = '2026-07-01' 時,engine 只列出並讀取那個 prefix 下的檔案 — 掃描量可能從 TB 降到 GB。
  • 選 partition key 的原則:低 cardinality、幾乎每個查詢都會 filter 的欄位(date 是最常見的)。用 user_id 這種高 cardinality 欄位做 partition 會產生百萬個小檔案(small-file problem),metadata 操作比讀資料還慢。

File Formats: Parquet vs CSV vs Avro

DimensionCSV / JSONAvroParquet (columnar)
LayoutRow-oriented textRow-oriented binaryColumn-oriented binary
SchemaNone(全是字串,型別靠猜)Embedded schema, strong evolution supportEmbedded schema + column statistics
CompressionPoorGoodExcellent(同欄位值相似 → 壓縮率高)
Read patternMust read whole row/fileWhole rowsRead only needed columns(column pruning)
Predicate pushdownNoNoYes — skip row groups using min/max stats
Splittable for parallel readAwkwardYesYes(row groups)
Best forHuman-readable exchange, tiny dataStreaming / Kafka messages, write-heavy ingestionAnalytics, ML training data — the lake default

Predicate pushdown: Parquet 在每個 row group 存了各欄位的 min/max 統計,engine 看到 WHERE amount $>$ 1000 時,會直接跳過 max 小於 1000 的 row groups — 連讀都不讀。加上 column pruning(只讀 SELECT 到的欄位),這就是為什麼同一份資料存 Parquet 的查詢成本常常只有 CSV 的十分之一以下。

直覺:分析查詢通常是「幾百個欄位裡只要 5 個,但要掃很多天」— columnar 格式讓你只付你要的那 5 欄的 I/O。反過來,streaming ingestion 是「一次寫一整筆 record」— row-oriented 的 Avro 比較自然,之後再 compact 成 Parquet。

ETL vs ELT & Orchestration

DimensionETLELT
OrderExtract → Transform(外部 engine)→ LoadExtract → Load(raw 直接進 warehouse/lake)→ Transform(用 warehouse SQL)
Transform engineDedicated servers (Informatica, custom Spark)The warehouse itself (BigQuery, Snowflake)
Raw data kept?通常不留 — transform 錯了要重抽留 — 隨時可以重新 transform
Who writes transformsData engineers (code)Analytics engineers / DS (SQL, dbt)
EraStorage 貴、compute 集中的年代Cloud warehouse compute 便宜且彈性

為什麼 ELT 贏了:cloud warehouse 讓「先全部載入、再用 SQL 慢慢整理」變得便宜,而保留 raw data 意味著 transform 邏輯錯了只要重跑 SQL,不用重新抽取。這催生了 dbt pattern — transformation 全部寫成 SQL SELECT models,用 Git 管版本、寫 tests、自動生成 lineage 文件,把 software engineering 的紀律帶進 SQL 世界。

Orchestration with Airflow-style DAGs

An orchestrator schedules tasks as a DAG (directed acyclic graph) with dependencies, retries, and alerting. Key concepts interviewers probe:

ConceptDefinitionWhy It Matters
Idempotency同一個 task 對同一個時間區間跑 N 次,結果都一樣Retry 和 backfill 的前提 — 用 overwrite partition 而不是 append
Backfill對歷史日期重跑 pipeline邏輯改了或上游修資料後,重建過去的結果
Retries失敗自動重試(含 exponential backoff)大部分失敗是 transient(網路、資源),自動恢復
Sensors等待上游條件成立才開跑(例如某個 partition 出現)避免在上游還沒到齊時就計算出錯的結果
Catchup / schedule每個 run 綁定一個 logical date,處理該區間的資料資料和時間區間對齊,才可能 idempotent

Non-idempotent Pipeline 是經典地雷

如果 task 是「把今天的資料 append 到結果表」,retry 一次就會重複資料、backfill 更是災難。正確設計:每個 run 負責一個明確的時間 partition,執行時整個 partition 覆寫(delete-then-insert 或 overwrite)。面試被問 pipeline design 時主動講出 idempotency,是很強的訊號。

Data Quality Checks in Pipelines

和 ML Pipelines 那頁的 data validation 直接相連 — 在 orchestration 層把品質檢查做成 DAG 中的 blocking tasks:

CheckExampleOn Failure
Freshness最新 partition 的 event time 距今小於 2 小時Block downstream, page on-call
Volume今日 row count 在 7 日移動平均的正負 30% 內Block + alert
Schema / contract欄位型別與 not-null 約束符合預期Block(上游 breaking change)
UniquenessPrimary key 無重複Block(replay bug)

原則同樣是 fail loud:寧可 dashboard 晚一天,也不要 model 默默用壞資料訓練。

Distributed Processing with Spark

Driver / Executor Model

A Spark application has one driver(解析你的程式、建立執行計畫、調度工作)and many executors(實際持有 data partitions 並執行運算的 worker processes)。資料被切成 partitions 分散在 executors 上平行處理。

Lazy Evaluation and the DAG

Transformations (filter, select, groupBy) do not execute immediately — Spark 只是把它們記錄成一個 logical plan。直到遇上 actioncount, write, collect)才會觸發:optimizer 把整條 transformation 鏈整理成 execution DAG(合併運算、把 filter 往資料源推),一次執行。這讓 Spark 能做全局最佳化,但也是新手困惑的來源 — 程式跑到 write 那行才爆錯,錯誤其實在前面的 transformation。

Narrow vs Wide Transformations

TypeData MovementExamplesCost
Narrow每個 output partition 只依賴一個 input partition — no networkfilter, select, withColumn, mapCheap, pipelined in memory
WideOutput partition 需要多個 input partitions 的資料 — 觸發 shufflegroupBy, join, distinct, orderBy, repartitionExpensive

Why shuffle is expensive: 所有 executors 把資料按 key 重新分組,寫到 local disk,再透過網路互相交換(all-to-all)。Disk I/O + network + serialization 三重成本,而且是 stage 之間的同步屏障 — 最慢的 partition 拖住所有人。

Partitioning and Skew Tips

ProblemSymptomFix
Data skew一個 task 跑 1 小時,其他 199 個 3 分鐘就完成Salting(把 hot key 加隨機後綴拆開)、AQE skew join handling
Join 一大一小表大 shuffleBroadcast join — 把小表複製到每個 executor,完全避開 shuffle
Too many small partitionsTask scheduling overhead 超過運算coalesce 減少 partition 數
Too few large partitionsOOM、平行度不足repartition 增加,或調 shuffle partitions 設定
重複使用中間結果同一段 lineage 重算多次cache() / persist() 明確物化

When Is pandas Enough?

SituationUseReasoning
Data fits in memory(單機 RAM 的一半以內,約小於 10-50 GB)pandas / Polars / DuckDB沒有 cluster 開銷、迭代快、除錯容易
中型資料、單機放不下但查詢簡單DuckDB on Parquet / warehouse SQLColumnar engine 單機就很能打
TB 級 join / aggregation、需要和 lake 深度整合Spark真正需要 distributed compute
Feature pipeline 要 train/serve 共用、排程化Spark or warehouse SQL和平台整合、可監控、可 backfill

不要為了履歷用 Spark

面試講到工具選擇時,「我們資料 8GB,我用 pandas 半小時搞定,不需要 Spark」比「什麼都上 Spark」更能展現 seniority。Spark 的啟動成本、除錯難度和 cluster 費用都是真實代價 — 先問資料量和成長速度,再選工具。

Batch vs Streaming in the Data Platform

DimensionBatchStreaming
TriggerSchedule(hourly / daily)Event arrival, continuous
LatencyMinutes to hoursSub-second to minutes
Throughput per unit costHigh(大塊處理攤薄開銷)Lower(常駐資源)
ComplexityLow — 容易 backfill、容易測試High — event time vs processing time、late data、exactly-once
Typical toolsSpark batch, dbt, warehouse SQLKafka / Kinesis + Flink / Spark Structured Streaming
Use cases報表、訓練資料、每日 metricsFraud 偵測、即時監控、real-time features

Streaming Ingestion into the Lake

典型 event pipeline:app SDK 發 events → Kafka / Kinesis(durable, ordered, replayable log — producer 和 consumer 解耦)→ 一個 sink job(Kafka Connect / Firehose / Spark Streaming)持續把 events 落到 lake 的 bronze 層 → 下游 batch jobs 接手清洗聚合。訊息系統的 replay 能力很關鍵:consumer 有 bug 時可以回捲 offset 重新消費。

Micro-batch vs True Streaming

ApproachHowLatencyExample
Micro-batch每隔一小段時間(秒級)收集一批一起處理SecondsSpark Structured Streaming
True streaming一筆 event 一筆處理MillisecondsFlink

大部分「real-time」需求(dashboard 每分鐘更新、feature 5 分鐘內 fresh)micro-batch 就綽綽有餘;毫秒級的 true streaming 只有 fraud、bidding 這類場景才需要。

Freshness vs cost tradeoff:latency 每降一個數量級,架構複雜度和成本大約升一個數量級。面試的加分回答是反問:「這個 metric 晚一小時會造成什麼商業損失?」— 大多數分析用途 daily batch 就夠,streaming 是為明確的 use case 服務,不是預設。

Cloud Big Data Services Map

The same logical layer maps to equivalent managed services on each cloud:

LayerAWSGCPAzure
Object storage (lake)S3Cloud Storage (GCS)Blob Storage / ADLS Gen2
Data warehouseRedshiftBigQuerySynapse Analytics
Managed Spark / processingEMRDataprocDatabricks on Azure / HDInsight
Serverless batch/stream processingGlueDataflowData Factory data flows
Streaming ingestionKinesis / MSK (Kafka)Pub/SubEvent Hubs
OrchestrationMWAA (managed Airflow) / Step FunctionsCloud Composer (managed Airflow)Data Factory
NoSQL key-valueDynamoDBBigtable / FirestoreCosmos DB
Relational OLTPRDS / AuroraCloud SQL / SpannerAzure SQL Database
BIQuickSightLookerPower BI

記法:分層記、不要逐一背 — 面試被問「你們是 GCP,我們是 AWS,你 OK 嗎?」時,正確的回答是概念一一對應:BigQuery 對 Redshift、Pub/Sub 對 Kinesis、Composer 對 MWAA,換雲只是換服務名,架構思維完全共通。

Which Database Should I Use? (Workload-driven)

WorkloadRight Tool (AWS example)Why
Transactional app backend(orders, users)RDS / Aurora (PostgreSQL)ACID, joins, row-oriented
Key-value at massive scale, single-digit ms(session, cart)DynamoDBPredictable latency, serverless scaling
Analytics over TBs(BI, ad-hoc SQL)Redshift(or BigQuery on GCP)Columnar, MPP scan performance
Cache / leaderboardElastiCache (Redis)In-memory, microsecond reads
Full-text / log searchOpenSearchInverted index
Raw event archive + ML training dataS3 + Parquet (+ Iceberg)Cheapest, open format, any engine
Time-series metricsTimestream(or InfluxDB)Time-partitioned compression and rollups

決策順序

先問 workload 的三件事:(1)access pattern — point lookup 還是大範圍掃描?(2)latency 需求 — ms 還是分鐘?(3)資料量和成長。答案幾乎自動決定資料庫類型;先選類型、再選雲上對應的服務。反著來(先迷戀某個服務)是面試的扣分回答。

Data Modeling for Analytics

Star Schema

Warehouse 的經典模型:中央的 fact table(事件/交易,數字 measures + 外鍵)連到多個 dimension tables(描述性屬性)。

Table TypeContentExampleSize
FactEvents / transactions: measures + dimension keysfact_orders(order_id, user_key, product_key, date_key, amount)巨大、持續成長
DimensionDescriptive attributesdim_user(user_key, country, signup_date, plan)小、變化慢

好處:BI 查詢變成固定模式 — fact join 幾個 dims、GROUP BY 維度、聚合 measures;維度屬性只存一份,改一次全部報表都對。

Grain

Grain = fact table 一列代表什麼(one row per order? per order line? per user per day?)。建模的第一個問題永遠是宣告 grain — grain 不清楚,所有的 join 和聚合都可能默默重複計算。這也是 SQL 面試 fan-out bug 的根源:fact join 到比它 grain 細的表,金額被複製多次,SUM 直接爆掉。

Slowly Changing Dimensions (SCD)

Dimension 屬性會變(user 搬家、改方案),怎麼處理歷史?

TypeStrategyHistoryExample Use
SCD Type 1Overwrite the old value不保留修正錯字、不影響分析的屬性
SCD Type 2Insert a new row with valid_from / valid_to (and is_current flag)完整保留分析必須「以當時狀態計算」時 — 例如用戶當時的 plan

SCD Type 2 是面試熱點:查詢時 fact 要 join 在 event_date BETWEEN valid_from AND valid_to 的那一列 dimension,才能還原「事件發生當下」的屬性。用 current 值回算歷史 = 常見的分析錯誤(例如把用戶現在的 premium 身分套用到他還是 free user 時的行為)。

Wide Tables vs Normalized

ApproachProsConsWhen
Normalized (star)Single source of truth, storage-efficient, flexible查詢要 join,對非技術用戶不友善Core warehouse layer
One Big Table (denormalized wide)查詢簡單、columnar warehouse 掃描快、適合餵 BI 和 ML資料重複、dimension 更新要重建、容易 metric 定義發散Gold layer / 特定主題的 mart

現代常見折衷:Silver 層維持 normalized star schema 作為 single source of truth,Gold 層用 dbt 物化成 wide tables 給 dashboard 和 ML 直接用 — 兩者不衝突,是不同層的產物。

Real-World Use Cases

Case 1: 建立實驗數據平台(A/B Testing)

你加入一家還在用 Google Sheets 算實驗結果的公司,要建立可信的實驗平台。設計:app 端 SDK 發 exposure 和 conversion events → Kinesis / Kafka → 落地到 S3 bronze(原始 events,append-only, Parquet, partitioned by date)→ 每小時 batch job 清洗成 silver(dedup、joining assignment logs、修正 late events)→ dbt 在 warehouse 建 gold 層 metrics tables(每個 experiment × variant × metric 一列,含 sample size 和 variance)→ 實驗 dashboard 和統計檢定直接讀 gold 表。

關鍵設計決策:exposure logging 要在 randomization 當下記錄(避免 selection bias);metrics 定義集中在 dbt models(避免每個 DS 自己算一套 CTR);bronze 永遠保留 raw events,實驗定義改了可以 backfill 重算。

Interview follow-ups:

  • 為什麼 events 要先落 lake 再進 warehouse,而不是直接寫進 warehouse?(成本、replay 能力、非結構化欄位的彈性、warehouse 不適合高頻小筆寫入)
  • Late-arriving events(手機離線補傳)怎麼處理?(watermark + 每天重跑最近 N 天的 partitions)
  • 怎麼確保兩個 DS 算同一個實驗得到相同數字?(single source of truth 的 metrics 層 — 這就是 gold 層存在的理由)

Case 2: Feature Pipeline 從 pandas 遷移到 Spark 的時機

你的 churn model feature pipeline 是一個每天跑的 pandas script,讀 warehouse 匯出的 CSV。一年後資料從 2GB 長到 60GB,script 開始 OOM、跑 6 小時。你要決定:加大機器記憶體?改寫成 Spark?還是把邏輯下推到 warehouse SQL / dbt?

分析框架:(1)60GB 其實還在「大機器 + Polars/DuckDB」能處理的範圍,最便宜的修法可能是換格式(CSV → Parquet)+ 換 engine,成本一天就能完成;(2)如果成長趨勢明確會到 TB 級、或需要和 lake 上的 event 資料 join,才值得付出 Spark 的複雜度;(3)如果邏輯全是 SQL 可表達的聚合,下推到 warehouse 用 dbt 管理可能是最好解 — 免維運、有 lineage、和其他表共用品質檢查。遷移到 Spark 時的重點:用 broadcast join 處理小 dimension、確認 shuffle partitions 設定、每天 overwrite 對應的 feature partition 保持 idempotent。

Interview follow-ups:

  • 你怎麼驗證遷移後 features 和舊 pipeline 一致?(同一天資料雙跑、逐欄位比對統計量 — 呼應 train-serving skew)
  • 什麼訊號告訴你「該上 Spark 了」?(資料超過單機記憶體數倍、需要跨 TB join、單機跑不進 SLA)
  • 為什麼 CSV 換 Parquet 就能救回一大段效能?(columnar + 壓縮 + 只讀需要的欄位)

Case 3: 選 BigQuery 還是 Self-host?

新創公司(8 人 data 團隊)要選分析平台:BigQuery(serverless, pay-per-query)還是自建(ClickHouse on Kubernetes)。決策維度:

DimensionBigQuery (managed)Self-hosted ClickHouse
Ops burden幾乎為零需要專人顧 cluster、升級、備份
Cost shape隨用量線性成長,query-heavy 時可能失控固定機器成本,大量查詢時單位成本低
Elasticity自動 scale,抗尖峰容量要預先規劃
Performance control有限(黑盒 optimizer)完全掌控(可調 engine、index)
Team size fit小團隊最佳解需要 infra 能力的團隊

給小團隊的合理建議:先用 managed(BigQuery),把工程時間花在產生商業價值的分析上;等 query 帳單成長到「一個工程師年薪」的量級,才值得評估 self-host — 而且因為資料存在開放格式的 lake(Iceberg/Parquet),遷移時搬的是 compute 不是資料,lock-in 有限。

Interview follow-ups:

  • Pay-per-query 模式下,怎麼防止一個失控查詢燒掉預算?(partition filter 強制、查詢 byte 上限、按 team 設 quota)
  • 什麼情況 self-host 明顯划算?(查詢量極大且穩定、latency 需求特殊、合規要求資料不出機房)
  • 怎麼降低對單一雲的 lock-in?(open table formats、SQL 標準化、把 transform 邏輯放 dbt 而不是 proprietary 工具)

Hands-on: Data Engineering in Python

PySpark: Read, Aggregate, Write

from pyspark.sql import SparkSession, functions as F

spark = SparkSession.builder.appName("daily_user_features").getOrCreate()

# Read only one day via partition pruning (dt is a partition column)
events = (
    spark.read.parquet("s3://lake/silver/events/")
    .filter(F.col("dt") == "2026-07-01")          # partition pruning: reads one prefix
    .select("user_id", "event_type", "amount")     # column pruning: Parquet reads 3 columns
)

# Narrow transformation (no shuffle)
purchases = events.filter(F.col("event_type") == "purchase")

# Wide transformation: groupBy triggers a shuffle by user_id
user_features = purchases.groupBy("user_id").agg(
    F.count("*").alias("purchase_cnt_1d"),
    F.sum("amount").alias("purchase_amt_1d"),
    F.avg("amount").alias("avg_order_value_1d"),
)

# Broadcast join: small dimension table copied to every executor (no shuffle)
users = spark.read.parquet("s3://lake/silver/dim_user/")
enriched = user_features.join(F.broadcast(users), "user_id", "left")

# Control output file count, then overwrite ONE partition (idempotent)
(
    enriched.repartition(8)
    .write.mode("overwrite")
    .parquet("s3://lake/gold/user_features/dt=2026-07-01/")
)

Airflow DAG Sketch

from airflow import DAG
from airflow.operators.python import PythonOperator
from airflow.sensors.external_task import ExternalTaskSensor
from datetime import datetime, timedelta

default_args = {
    "retries": 2,                              # transient failures auto-recover
    "retry_delay": timedelta(minutes=10),
}

with DAG(
    dag_id="daily_user_features",
    start_date=datetime(2026, 1, 1),
    schedule="0 3 * * *",                      # daily at 03:00, one run per logical date
    catchup=True,                              # enables backfill of past dates
    default_args=default_args,
) as dag:

    # Sensor: wait until upstream events table for this date is ready
    wait_for_events = ExternalTaskSensor(
        task_id="wait_for_events",
        external_dag_id="ingest_events",
        timeout=3600,
    )

    # Each task processes exactly one date partition -> idempotent reruns
    build_features = PythonOperator(
        task_id="build_features",
        python_callable=run_spark_job,          # submits the PySpark job above
        op_kwargs={"ds": "{{ ds }}"},           # logical date injected by Airflow
    )

    validate = PythonOperator(
        task_id="validate_output",
        python_callable=check_row_count_and_nulls,  # fail loud -> blocks downstream
        op_kwargs={"ds": "{{ ds }}"},
    )

    wait_for_events >> build_features >> validate

dbt-style SQL Model

-- models/gold/fct_daily_user_metrics.sql
-- dbt manages dependencies via ref(); materialized as an incremental table

{{ config(materialized="incremental", unique_key="user_date_key") }}

with purchases as (

    select
        user_id,
        date(event_ts)  as event_date,
        amount
    from {{ ref("stg_events") }}               -- silver-layer staging model
    where event_type = 'purchase'
    {% if is_incremental() %}
      and date(event_ts) >= dateadd(day, -3, current_date)  -- reprocess late data
    {% endif %}

)

select
    user_id || '_' || event_date as user_date_key,   -- declared grain: user x day
    user_id,
    event_date,
    count(*)     as purchase_cnt,
    sum(amount)  as purchase_amt
from purchases
group by user_id, event_date

Interview Signals

What interviewers listen for:

  • 你能畫出資料從 OLTP source 到 dashboard/model 的完整路徑,並說出每一層的職責
  • 你會先問資料量、latency 需求和成長速度,再選工具 — 而不是所有東西都上 Spark 或 streaming
  • 你主動提到 idempotency、backfill、partition overwrite 這些 pipeline 可靠性的關鍵字
  • 你能解釋 Parquet + partitioning 為什麼省錢(column pruning、predicate pushdown、partition pruning)
  • 你把雲服務當成分層概念的實作(BigQuery ≈ Redshift ≈ Synapse),換雲不換架構思維

Practice

Flashcards

Flashcards (1/10)

Data lake、data warehouse、lakehouse 的核心差異?

Warehouse: schema-on-write、結構化、查詢快、治理強、儲存較貴。Lake: 開放格式檔案放 object storage、schema-on-read、超便宜、什麼型態都收,但預設治理弱。Lakehouse: 在 lake 上加 table format(Delta/Iceberg/Hudi)提供 ACID、schema enforcement、time travel — lake 的成本 + warehouse 的保證。

Click card to flip

Quiz

Question 1/10

為什麼不直接在 production OLTP database 上跑分析查詢?

Mark as Complete

3/5 — Okay