关于 etl-incremental-patterns
ETL Incremental Patterns 是一项关于增量加载、回填和流水线编排的参考技能,帮助数据工程师根据数据源能力、表规模和刷新要求选择加载策略。
主要功能
- 01基于时间戳的增量加载
- 02变更数据捕获事件处理
- 03并行回填日期范围
- 04通过表交换进行全量刷新
- 05流水线步骤状态模式
- 06加载策略决策矩阵
适用场景
- 01按时间戳同步大型数据表
- 02处理 CDC 的 INSERT、UPDATE 和 DELETE 事件
- 03并行加载历史数据
- 04使用交换模式刷新关键数据表
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ majesticlabs-dev/ majestic-marketplace --skill etl-incremental-patterns安装后在 Claude Code 中输入/etl-incremental-patterns确认已加载。
详细介绍
ETL 增量模式
用于增量数据加载和回填操作的模式。
回填策略
from datetime import date, timedelta
from concurrent.futures import ThreadPoolExecutor, as_completed
def backfill_date_range(
start: date,
end: date,
process_fn: callable,
parallel: int = 4
) -> None:
"""Backfill data for a date range."""
dates = []
current = start
while current <= end:
dates.append(current)
current += timedelta(days=1)
# Process in parallel with controlled concurrency
with ThreadPoolExecutor(max_workers=parallel) as executor:
futures = {executor.submit(process_fn, d): d for d in dates}
for future in as_completed(futures):
d = futures[future]
try:
future.result()
print(f"Completed: {d}")
except Exception as e:
print(f"Failed: {d} - {e}")
# Usage
backfill_date_range(
start=date(2024, 1, 1),
end=date(2024, 3, 31),
process_fn=process_daily_data,
parallel=4
)
增量加载模式
基于时间戳的增量加载
def incremental_by_timestamp(table: str, timestamp_col: str) -> pd.DataFrame:
last_run = get_last_run_timestamp(table)
query = f"""
SELECT * FROM {table}
WHERE {timestamp_col} > :last_run
ORDER BY {timestamp_col}
"""
df = pd.read_sql(query, engine, params={'last_run': last_run})
if not df.empty:
set_last_run_timestamp(table, df[timestamp_col].max())
return df
变更数据捕获(CDC)
def process_cdc_events(events: list[dict]) -> None:
for event in events:
op = event['operation'] # INSERT, UPDATE, DELETE
data = event['data']
if op == 'DELETE':
soft_delete(data['id'])
else:
upsert(data)
全量刷新并交换
def full_refresh_with_swap(df: pd.DataFrame, table: str) -> None:
temp_table = f"{table}_temp"
df.to_sql(temp_table, engine, if_exists='replace', index=False)
with engine.begin() as conn:
conn.execute(text(f"DROP TABLE IF EXISTS {table}_old"))
conn.execute(text(f"ALTER TABLE {table} RENAME TO {table}_old"))
conn.execute(text(f"ALTER TABLE {temp_table} RENAME TO {table}"))
conn.execute(text(f"DROP TABLE {table}_old"))
流水线编排
from enum import Enum
from dataclasses import dataclass, field
class StepStatus(Enum):
PENDING = "pending"
RUNNING = "running"
SUCCESS = "success"
FAILED = "failed"
SKIPPED = "skipped"
@dataclass
class PipelineStep:
name: str
func: callable
dependencies: list[str] = field(default_factory=list)
status: StepStatus = StepStatus.PENDING
error: str | None = None
class Pipeline:
def __init__(self, name: str):
self.name = name
self.steps: dict[str, PipelineStep] = {}
def add_step(self, name: str, func: callable, depends_on: list[str] = None):
self.steps[name] = PipelineStep(name, func, depends_on or [])
def run(self) -> bool:
for step in self._topological_sort():
# Skip if dependencies failed
if any(self.steps[d].status == StepStatus.FAILED for d in step.dependencies):
step.status = StepStatus.SKIPPED
continue
step.status = StepStatus.RUNNING
try:
step.func()
step.status = StepStatus.SUCCESS
except Exception as e:
step.status = StepStatus.FAILED
step.error = str(e)
return all(s.status == StepStatus.SUCCESS for s in self.steps.values())
def _topological_sort(self) -> list[PipelineStep]:
# Implementation of topological sort for dependency ordering
...
加载策略决策矩阵
| 场景 | 模式 | 适用时机 |
|---|---|---|
| 小型表(<100K 行) | 全量刷新 | 每日/每小时加载 |
| 带时间戳的大型表 | 时间戳增量加载 | 持续同步 |
| 源支持 CDC | CDC 事件 | 实时更新 |
| 一次性历史数据加载 | 并行回填 | 初始迁移 |
| 关键表 | 交换模式 | 零停机刷新 |
评论
支持 Markdown