数据工程师应该掌握的 6 个技能

如果我现在才进入数据工程领域,我会感到极度手足无措。大量的工具、大量的技能,而且我还没把 AI 相关的东西摆到桌面上来。

我在某处读到过,这个时代最有效的学习方式,是去学习那些不会改变的东西。回顾我作为数据工程师的旅程,我意识到确实存在这样的一些东西。

在这篇文章中,我分享了我认为每个数据工程师都应该掌握的六项技术技能。它们短期内不会过时。

1、在我们继续之前

对我来说,学习某样东西最重要的方面,是拥有一个可靠的反馈回路,并有人为你提供反馈:你的朋友、你的资深同事,或者互联网社区。

让 Gemini 或 ChatGPT 扮演一个了解你正在做什么的人(例如,"想象你是一位有 20 年经验的数据工程师,帮我点评一下这个转换 SQL 脚本")也不失为一个好选择。

关键是要知道你所做的事情是否走在正确的轨道上。

2、数据建模

你很快会意识到一个事实:后续的每一个流程——每一条管道、每一个查询、每一个机器学习模型——都建立在数据模型所定义的结构之上。

如果数据仓库是一座建筑,那么数据建模就是建筑蓝图。没有它,我们根本不知道下一步该做什么。我们可以盲目地加载和查询数据几个月;然而,噩梦很快就会来临:

  • 维护成本:没有清晰的蓝图,我们会留下一堆乱七八糟的 SQL 脚本和数据表,使维护成为一个昂贵且令人沮丧的过程
  • 处理效率低下:针对设计糟糕的结构进行查询,通常既慢又消耗大量资源
  • 数据完整性问题:如果不强制实施关系和约束,就很难确保数据完整性,这可能使信息变得不可靠
  • 奇怪的洞察:没有可靠的数据以及标准的加载和检索方式,分析师和数据科学家很可能会产出糟糕的报告和机器学习模型
  • 缺乏信任:业务用户随后会利用这些奇怪的洞察来做决策,这可能导致代价高昂的错误。流程很快就会多出一步:检查洞察是否有效

让我们想象一个更美好的场景:如果我们有一套精心设计的数据建模方案摆在那里:

  • 共同语言:有了数据建模,我们就有了对组织数据的共享、统一视图,促进了利益相关者之间的清晰沟通
  • 数据质量和完整性:建模约束和关系为我们确保数据质量提供了一个良好的起点
  • 减少错误:数据分析师确切知道如何查询某条洞察。数据工程师确切知道数据将被加载到哪个位置。所有必要的转换都事先完成,让数据组织得井井有条,随时可以对外提供。一个好的数据模型会尽可能减少错误。

2.1 如何学习它?

我们首先需要知道的是,数据建模是一个从高层业务概念走向底层技术实现的过程:

  • 概念数据模型:这是最高层次的视图,专注于捕捉业务需求。它识别核心业务实体(例如客户产品订单)以及它们之间的关系。在这个阶段我们不关心底层技术。概念模型用于与利益相关者对齐。
  • 逻辑数据模型:这一层比概念模型更详细。我们为每个实体添加属性(例如,Customer 有 first_name、email、customer_id),确定主键和数据类型(例如,string、integer)。这里我们同样不关心技术。逻辑模型充当业务概念与物理实现之间的桥梁。
  • 物理数据模型:这是针对特定数据库系统的具体实施蓝图。它将逻辑模型转化为表、列、约束或优化技术,例如聚簇(clustering)或分区(partitioning)。这里我们使用所选技术的术语和特性(例如,BigQuery、Snowflake、Databricks)。

接下来是探索数据建模方法论。

Kimball 方法(维度建模)提供了一种自下而上的方法,专为快速、易于理解的分析而优化。该方法在《数据仓库工具箱》中有详细记载,该书是维度建模的权威指南。

其核心结构是星型模式,由一个包含定量度量或事件的中心事实表和提供描述性上下文的维度表(例如,客户详情、产品信息、日期)包围组成。

相比之下,Inmon 方法采取自顶向下的方式,主张创建一个集中的、高度规范化(通常达到第三范式,即 3NF)的企业数据仓库(EDW)。这个 EDW 充当唯一的真相来源。

然后从这个规范化的核心构建部门级数据集市,以满足特定的分析需求。这种方法更复杂、敏捷性更低,但在大规模数据集成和最小化数据冗余方面表现出色。

我建议先学习 Kimball 方法,因为我个人认为它更容易上手和实践。如果我要重新学一遍 Kimball,我会尝试从书中掌握它的基本原理,包括事实、维度以及四步流程。如果你不想在理论上花太多时间,那么阅读指南正是你需要的。

之后,我们需要实践:

  • 选择你最喜欢的业务领域。
  • 从定义业务问题开始。例如,"我们需要跟踪哪些关键绩效指标?"答案(例如,每日销售收入、新增订阅用户数)将构成事实表的基础。
  • 然后,问"我们希望如何对这些指标进行切分?"答案(例如,按客户地理区域、按产品类别、按时间)将定义维度表。
  • 构建一个简单的星型模式。
  • 检查你的建模能否帮助你顺畅地回答你的问题。
  • 如有需要,调整并改进你的建模。
  • 获取反馈并迭代。

3、Git

我们很少独自工作。我们很少只与单一版本的数据管道、Python 应用或 SQL 脚本打交道。组织需要一种方式对工作做版本控制并支持协作。

Git 就是做到这一点的标准方式。它是一个由 Linux 开发社区于 2005 年开发的开源分布式版本控制系统。如果你对 Git 完全陌生,你可能会发现它需要花不少时间学习。(为什么我们需要 git clone,而明明可以压缩并下载整个仓库?)。

然而,你很快会体会到 Git 的版本控制能力,它在开发中为你节省大量时间,也让分享你的工作变得更加容易。无论你的代码有多好,如果你不懂 Git,你就很难与他人协作。

防止生产环境发生奇怪的事情、追踪 bug(为什么之前的版本没发现这个 bug)、构建 CI/CD 流水线、将你的工作与队友隔离开来,等等。

有无数的好处和实际用途。

3.1 如何学习它?

在这篇文章列出的技能中,我认为 Git 是最容易学习的。在 GitHub 上做一个玩具项目、在笔记本电脑上安装 Git、练习各种命令。

关键是在实践之前理解它的基本原理。

Git 以快照的形式存储数据,通过利用指针提供强大的分支能力。

一次提交(commit)是项目在特定时间点的完整快照。它是仓库中每个文件和文件夹在提交时刻的完整画面。一次提交会有指向其父提交的指针。

Git 分支只是一个可以移动的、指向某次提交的指针。

更多细节,你可以查看我写的 15 分钟学习 Git 指南:Git for Data Engineers

4、SQL

如果你在数据领域工作,无论你是数据工程师、数据分析师还是数据科学家,你都"说"SQL。这种语言诞生于 20 世纪 70 年代,用于操作和检索关系数据库中的数据。从那时起,它作为处理这些数据库的主要接口,在全球范围内被越来越广泛地采用。

OLAP 数据库的演进以及 DBT、SQLMesh 等转换工具的兴起,使 SQL 成为数据转换的有吸引力的选择——而数据转换过去主要由 Java 或 Python 等过程式语言处理。一些云数据仓库,如 BigQuery,甚至允许用户用 SQL 做机器学习。

数据工程师用 SQL 做很多事情。

4.1 如何学习它?

首先,学习语法。

从简单开始,先处理单张表:SELECT、FROM、WHERE、GROUP BY、ORDER BY、HAVING、SUM、COUNT、LIMIT…… 用于检索数据,以及 INSERT、UPDATE、DELETE 用于修改数据。

然后,我们开始处理多张表。学习 INNER JOIN、LEFT JOIN、RIGHT JOIN 和 FULL OUTER JOIN 之间的区别。

接下来,当进入 WINDOW FUNCTION(窗口函数)时,难度会稍微加大。和 GROUP BY 一样,它对行组执行计算,但两者有区别:

  • GROUP BY 会折叠行。它把多行聚合成单个汇总行。例如,SELECT country, SUM(sales) FROM products GROUP BY country 会为每个类别返回一行,显示该类别的销售总额。
  • 窗口函数 对一行"窗口"进行操作,但不会折叠它们。它们根据定义的窗口为每一行返回一个值。例如,
  • SELECT country, SUM(sales) OVER (PARTITION BY country) AS category_total_sales FROM products 会返回所有原始产品行。但是,它会在每一行上添加一个新列(category_total_sales),显示该产品所属类别的销售总额。

然后,我们来到 CTE(公共表表达式)。它们对于将复杂查询分解为逻辑清晰、可读的步骤至关重要,这提高了可维护性。

然而,仅学习语法是不够的。数据工程师必须知道底层发生了什么,因为我们不仅要编写 SQL 查询,还要编写优化过的查询。理解执行顺序至关重要。一个完整的查询会按照以下顺序执行。

  1. FROM / JOIN:数据库首先识别所需的表,并执行任何连接以创建完整的数据集。
  2. WHERE:然后过滤这个数据集,跳过不满足条件的行。(例如,X > 3)
  3. GROUP BY:剩余的行根据一列或多列的值进行分组,为聚合做准备(例如,SUM、COUNT、AVG……)
  4. HAVING:行分组后,此子句过滤掉不满足聚合条件的记录(例如,SUM(X) > 3)
  5. SELECT:引擎处理 SELECT 列表,确定最终结果中包含哪些列、表达式和聚合值。窗口函数也在这里处理。
  6. DISTINCT:如果指定了,则从结果集中移除重复行。
  7. ORDER BY:最终结果集根据指定的列或表达式进行排序。
  8. LIMIT / OFFSET:查询将输出限制为特定数量的行。
注意:一些数据库(如 BigQuery)还支持一个非常有用的子句,叫做 QUALIFY,它根据窗口函数的值过滤记录。

5、Python

正如我提到的,数据工程师将 SQL 用于各种目的,但不是所有事情。Python 可以弥补这一点。

你看到重复的任务并想将其自动化。Python 可以做到。

你面临难以用 SQL 表达的复杂转换。Python 配合 PySpark、Pandas 或 Polars 可以帮上忙。

数据来自许多系统。Python 可以通过 REST API 帮助拉取它们。

你需要编排许多数据管道步骤。Python 可以借助 Airflow 或 Dagster 等工具提供帮助。

或者,你想构建一个数据应用。Python 可以借助 Streamlit 或 FastAPI 等后端框架提供帮助。

学习 Python 是必须的。

5.1 如何学习它?

与其他语言相比,学习 Python 相当容易,因为它的语法简单得多。有大量的资源可以帮助我们学习如何在 Python 中编写函数、if 子句或类。

然而,仅学习语法永远不够。再说一次,我们很少独自工作。写代码不难,但写出可读、可维护、可扩展的代码需要时间。我们中的许多人都是通过自学 Python 开始这段旅程的;因此,写出凌乱的代码是可以理解的。

随着时间的推移,我们需要关心与我们共事的其他人。无论你的 Python 程序性能多好,如果你的同事不明白你在做什么,或者觉得扩展你的工作极其困难,那么你漂亮的代码就毫无用处。

尽早注意编写有条理的代码。学习设计模式(Python 通用数据管道专用)、SOLID 等编码原则,或者读一读《代码整洁之道》

一开始这可能会很无聊,因为它不会给你带来 Python 程序第一次运行时的感觉。但是,当你添加一段代码而没有让应用崩溃、看到同事毫不费力地无缝接手你的工作、或者有人把你的工作当作他们组织代码的参考时,那种感觉会更加令人满足。

6、OLAP 系统

哦哦,这是我最喜欢的一个。

数据仓库是一个逻辑实体,它整合来自多个来源的数据以满足分析需求。然而,仓库需要一个物理数据库来存储和提供数据。过去,组织也使用支撑其应用的数据库来达到这个目的。

随着时间推移,越来越多的公司意识到,他们需要从数据中提取洞察以获得商业优势。数据库研究者看到了机会。事务型数据库(OLTP)无法很好地服务分析工作负载,因为它们本来就不是为此设计的。

OLAP 系统的繁荣开始了。BigQuery、Databricks、Snowflake、Redshift 或 Clickhouse。它们被设计用来以最先进的优化技术处理 TB 甚至 PB 级的查询。

如今,OLAP 数据库是数据基础设施中最重要的组成部分。大多数与数据相关的任务都在这里发生:摄取数据、转换数据、提供数据,或执行数据治理。

6.1 如何学习它?

学习任何 OLAP 系统的关键在于理解两件事:它如何处理数据以及它如何存储数据。好消息是,这些系统有一些共同点:

总体:大多数 OLAP 系统采用无共享(share-nothing)架构;计算层和存储层分离以实现高可扩展性。

处理:由于数据量巨大,数据通常由多个工作节点处理。这些系统还采用向量化执行和/或代码生成等技术来提升性能。

存储

  • 数据还带有丰富的元数据,帮助查询引擎在处理查询时尽可能跳过更多数据。
  • 为了实现版本控制并支持工作负载隔离(ACID 中的"I"),这些系统不允许覆盖数据,因为已写入的数据是不可变的,变更会导致写入新文件。
  • 为了实现可扩展性和成本效益,大多数系统使用对象存储(或具有共享对象存储特性的存储)。

记住这些要点,你就可以探索任何你想要的 OLAP 系统了。对于具体的解决方案,最好的方法就是亲自试一试。大多数云数据仓库都为其服务提供试用期。

试一试,应用他们推荐的最佳实践,看看它对数据治理有什么帮助,理解它的定价模式,以及它如何与其他系统集成。

湖仓一体(lakehouse)范式的兴起意味着 OLAP 系统不再是厂商的专属领域。一个查询引擎(Spark、Trino)+ 对象存储(GCS、S3)+ 表格式(Delta Lake、Iceberg),你就拥有了自己的 OLAP 系统。上面提到的观察(总体、处理、存储)在这里依然适用。

与云数据仓库相比,自己管理这些系统需要付出更多努力,但作为回报,你对你的 OLAP 系统拥有更多的控制权。

7、编排(Orchestration)

当我们在做个人项目时,一个单独的 SQL 脚本或 PySpark 应用就足够了。然而,在生产环境中事情会变得复杂,因为你的团队有许多 dbt 模型和 Python 脚本需要运行。

更重要的是,它们需要按顺序运行。一个将数据加载到暂存表的任务必须成功完成,转换任务才能开始;而转换任务又必须在最终报表表更新之前完成。

手动管理这种复杂性不是解决办法。Apache Airflow 和 Dagster 等工具应运而生。除了 OLAP 系统之外,数据编排工具是数据基础设施中不可或缺的一部分。

它自动化了整个数据工作流的调度、执行、监控和管理。这些工作流通常表示为有向无环图(DAG),图中每个节点是一个任务,有向边表示任务之间的依赖关系。

这些工具的必要性源于生产级数据系统的关键需求:

  • 依赖管理:编排器确保下游任务只在其所有上游依赖完成后才运行。这正是我们想要的——例如,从两个来源拉取 API,然后将它们连接起来。
  • 调度:它们提供超越简单基于时间触发的复杂调度能力,支持类 cron 的调度、基于事件的触发(例如,当文件到达 S3 时运行)或数据感知的调度(例如,当上游数据资产可用时运行)。
  • 错误处理和重试:任何事情都可能失败;网络问题、API 服务器宕机或 SQL 语法错误都很常见。这些系统提供内置机制来重试失败的任务并自动进行数据回填。
  • 监控和可见性:编排工具还提供用户界面,给出所有数据管道的完整可视化概览。它们让工程师能够监控 DAG 运行的状态、检查单个任务的日志,并在失败时接收告警,为数据平台的健康状况提供关键的可见性。

7.1 如何学习它?

记住这些要点

基于任务 vs 基于资产的编排:你会在大多数编排工具中看到这两种方法。第一种方法说的是"先运行这个作业,再运行那个作业"(Airflow 就是按这种方法设计的),而后者问的是"保持这些资产(表、模型……)是最新的吗?"(Dagster 就是按这种方法设计的)。

幂等性和回填:这是可靠数据管道的两个关键概念。

  • 幂等性意味着使用相同输入多次运行一个任务会产生相同的结果(例如,f(x) = x * 1)。幂等管道可以在失败后安全重试,而不会产生重复数据或其他副作用。实现幂等性的一个常见模式是设计覆盖特定数据分区(例如,某一天的数据)而不是追加到该分区的作业。
  • 回填是为历史时段运行管道以重新处理数据的过程,也许是为了修复原始逻辑中的 bug,或者纳入延迟到达的数据。幂等设计是安全、轻松回填的先决条件。编排工具提供了在特定日期范围内触发和管理这些回填运行的机制。

对于具体工具:

  • 弄清楚你的凭证(如 API 令牌或云服务账号)是如何管理的。
  • 理解这些工具如何隔离任务。
  • 依赖:Dagster 支持每条数据管道拥有自己的一组 Python 依赖,而 Airflow 在全局层面管理依赖。
  • 资源隔离:Dagster 中的每个任务都在一个专用的 Kubernetes Pod 中运行。最初,Airflow 被设计为一组 Celery 工作节点,任务可以在同一工作节点上运行。后来,Airflow 也支持将任务作为 Kubernetes Pod 运行。
  • 理解这些因素将让你更容易维护和监控生产级环境。
  • 除了提供的抽象之外,我还可以用哪些其他抽象来扩展工具的功能?(例如,Airflow 有 Hook 和 Operator 的概念,允许用户自定义)
  • 这些工具已经对常见的数据源和数据目标有大量支持。然而,这并不全面。按照工具的最佳实践,学习如何扩展对所需数据源/数据目标的支持至关重要。

下一步是在你的笔记本电脑上运行这个工具并编写一些 DAG。Apache Airflow 是一个很好的起点,因为它拥有庞大的社区和大量的集成。

8、结束语

感谢你读到最后。

在这篇文章中,我概述了六个我认为每个数据工程师都应该优先掌握的技术技能。我分享了每项技能、它们为什么重要,以及我基于观察和经验高效学习和使用它们的体会。

当然,还有其他我们需要学习的东西,比如数据治理、云基础设施、Docker 和 bash 脚本。但我相信,掌握数据建模、Git、SQL、Python、OLAP 系统和编排,将为我们的职业生涯打下坚实的基础。

而且别忘了反馈回路。它是你掌握一项技能快慢的决定性因素。

好了,下次见。


原文链接: 6 technical skills every data engineer should have

汇智网翻译整理,转载请标明出处