AWS 大数据深度剖析(第四部分):Glue Catalog、Athena 与 Lake Formation
AWS Glue Data Catalog 如何充当数据湖的中央目录,以及 Athena 如何用无服务器 SQL 查询 S3 上的 Parquet 与 Iceberg 表。
数据已经落到了 S3 上——Athena、Spark、SageMaker 怎么知道「这是一张表,它有这些列」?答案是:Glue Data Catalog。
表注册好之后,谁来执行 SQL?答案是:Athena(无服务器)/ EMR Spark(重负载)/ Redshift(高并发 BI)。
谁来控制「哪些字段能被哪些人看到」?答案是:Lake Formation。
为什么你需要一个中央元数据目录
没有 Catalog 会发生什么?下面是一个常见的灾难场景:
团队 A:在 Athena 中创建了一张按 dt 分区的 `events` 表
团队 B:用 EMR Spark 以自己的 schema 读取 events,发现某个列的类型对不上
团队 C:用 SageMaker 做训练,CSV 模式 + 硬编码列名
三个团队,三套 schema,没人知道哪一套才是对的——数据治理就此崩溃。
Glue Data Catalog 就是唯一可信来源(single source of truth):每个引擎都从同一个地方读取表定义——一个元数据存储统御一切。
AWS Glue Data Catalog 详解
它是什么——以及它不是什么
它是:一个只存储元数据的服务(即 Metastore)。 它不是:数据库(它不存业务数据),也不是查询引擎(它不跑 SQL)。
打个比方:它就像图书馆的卡片目录——它告诉你「《活着》这本书在 3 楼 B 区第 5 排第 12 个位置」。书本身在 3 楼。
三级层次结构
Glue Data Catalog ← 每个 AWS 账户一个(全局)
└── Database ← 命名空间(类似于一个「schema」)
└── Table ← 单张表
├── Schema(列名、类型)
├── Location (s3://...) ← 数据在 S3 中的位置
├── Partitions (dt=...) ← 分区定义
├── Storage format(Parquet / Iceberg / CSV)
└── 其他属性
数据进入 Catalog 的四种方式
| 方式 | 最适用场景 | 自动化程度 |
|---|---|---|
| Zero-ETL / 基于 DMS 的 Zero-ETL | Aurora / RDS MySQL CDC | 全自动 |
| Glue Crawler | 已有的 S3 数据;自动推断 schema 并注册 | 高 |
| Glue ETL Job(写入时注册) | Spark 写入新分区并自动注册 | 中 |
| 手动 CREATE TABLE / Terraform | 完全受控的生产环境 | 低——但最稳定 |
生产最佳实践:用手动 / Terraform 来定义 ODS / DWD / DWS / ADS 的表 schema(可控)。Crawler 只用于探索性数据。
什么是 Glue Crawler?
Crawler 是一个「扫描 S3 并自动建表」的工具:
- 你给它一个 S3 路径
- 它扫描几个文件,推断列类型和分区
- 它在 Catalog 中自动注册这张表
优点:方便。 缺点:推断出的类型可能出错(例如把 string 推断成 int),分区检测也可能不稳定。在生产环境中,务必审查 Crawler 的输出。
Iceberg 表是特殊的
Iceberg 表不会把 Parquet 文件路径注册到 Catalog 中,而是注册一个指向 Iceberg metadata.json 文件的指针:
ods_user 表在 Catalog 中的条目:
TBLPROPERTIES:
table_type = 'ICEBERG'
metadata_location = 's3://.../ods_user/metadata/v123.json'
每次写入时:Iceberg 会写出一个新的 metadata.json,然后 Catalog 原子性地将 metadata_location 指针更新到新版本。
关键洞察:每个读取 Iceberg 表的引擎,都会先从 Catalog 获取当前的元数据指针,然后解析元数据以得到一份精确的文件清单(manifest)。这正是数据湖中实现 ACID 事务的方式。
跨账户与跨区域
- 同账户、同 Region:直接共享
- 跨账户:通过 Lake Formation 资源共享(Resource Sharing) 授权访问
- 跨 Region:使用 Glue 跨区域 Catalog(Cross-Region Catalog)(2024 年起可用)
定价
非常便宜:
- 前 100 万个对象(表 + 分区):免费
- 之后:每月每 100 万个对象 1 美元
- API 请求:每月前 100 万次免费,之后每 100 万次 1 美元
在实践中,对于任何真实的数据仓库,这项成本都可以忽略不计。
官方文档:
Amazon Athena:无服务器 SQL 查询
什么是 Athena?
一句话概括:给它一张已在 Glue Catalog 中注册的表,再加上一条 SQL 查询,它就会执行查询并返回结果。无服务器,按扫描量计费。
其底层引擎是 Trino(前身为 Presto,最初由 Facebook 开源的分布式 SQL 引擎),由 AWS 托管并优化。
一次查询在内部是如何执行的
四个步骤:
- 解析 SQL——生成逻辑计划
- 查询 Glue Catalog——获取表定义、分区列表、文件位置
- 分区裁剪 + 谓词下推——精确确定需要读取哪些文件和哪些列
- 并行的 Trino worker 读取 S3——聚合结果——将输出写入 S3——返回
整个过程对你是透明的:你提交 SQL,拿回结果。AWS 把 Trino 集群完全隐藏在幕后。
计费模型
按扫描的字节数计费(在 us-east-1 约为 $5/TB)。理解这一点是控制成本的关键。
「扫描的字节数」指的是从 S3 读取的 Parquet 数据,而不是结果集的大小:
-- 假设 ods_event 总共 1 TB
SELECT COUNT(*) FROM ods_event; -- scans 1 TB → $5
SELECT COUNT(*) FROM ods_event WHERE dt='2026-05-10'; -- scans 30 GB (one day) → $0.15
SELECT user_id FROM ods_event WHERE dt='2026-05-10'; -- scans 3 GB (one day + one column) → $0.015
头两个数量级的成本节省来自数据布局——这正是为什么 Parquet + 分区 + Iceberg 是一套必备组合。
性能优化技巧(按收益排序)
| # | 技巧 | 节省 |
|---|---|---|
| 1 | 将 CSV/JSON 转为 Parquet | 70-90% |
| 2 | 按 dt 分区并使用 WHERE dt=’…‘ | 90%+ |
| 3 | 谓词下推(利用 Parquet 列统计信息 / Iceberg) | 50-90% |
| 4 | 合理设置文件大小(128-512 MB) | 减少约 30% 的元数据开销 |
| 5 | 使用 Iceberg 而非 Hive 表 | 更精确的文件级跳过 |
| 6 | LIMIT + 列裁剪(用 SELECT col1, col2 而非 SELECT *) | 50-90% |
| 7 | 在 Workgroup 中设置最大扫描量限制 | 防止失控查询 |
Workgroup(工作组)
Workgroup 是 Athena 内部的「配置容器」,它把以下内容打包在一起:
| 设置项 | 用途 |
|---|---|
| 引擎版本 | v2 / v3(完整支持 Iceberg + 更好的性能需要 v3) |
| 结果位置 | 查询结果写入哪个 S3 桶 |
| 加密 | 结果的加密配置 |
| 成本限制 | 每条查询的最大扫描量 / 每个 Workgroup 的最大扫描量 |
| 数据用量控制 | 阈值告警 |
| 标签(Tags) | 用于成本分摊 |
生产最佳实践:每个团队或业务单元一个 Workgroup,从而实现:
- 账单拆分(CloudWatch 按 Workgroup 出报表)
- 成本治理(设置上限以防止昂贵的失控查询)
- 引擎隔离(某些团队仍在用 v2,而不影响其他团队)
Provisioned Capacity(预置容量,2023 年起)
普通的 Athena 是无服务器的,但有时业务需要严格的 SLA(例如一个必须在 5 秒内返回的 BI 看板——按需模式偶尔会排队)。
Athena Provisioned Capacity:预先购买专用的计算单元(DPU),以保证稳定的延迟。
- 最少 24 个 DPU(约 $20/小时),按小时计费
- 适用于对 SLA 有严格要求的工作负载;常规分析并不需要它
Athena 也能写:CTAS 与 INSERT INTO
Athena 并非只读——它也可以写入数据:
-- CREATE TABLE AS SELECT
CREATE TABLE dwd_user_action
WITH (
format = 'PARQUET',
partitioned_by = ARRAY['dt'],
location = 's3://my-bucket/warehouse/dwd/user_action/'
) AS
SELECT * FROM ods_event WHERE event_type = 'click';
-- Insert into a new partition
INSERT INTO dwd_user_action
SELECT * FROM ods_event WHERE dt = '2026-05-10';
-- Iceberg table UPDATE / DELETE / MERGE (v3 supports this)
MERGE INTO dwd_user_action t USING staging s
ON t.event_id = s.event_id ...
这就是为什么轻量级的 ODS / DWD / DWS / ADS 分层转换最好交给 Athena CTAS(最便宜的选项),而重型处理则交给 EMR / Glue Spark。
官方文档:
Athena 与其他查询引擎的对比
Athena vs. Redshift
| Athena | Redshift | |
|---|---|---|
| 架构 | 无服务器,存算分离(数据在 S3) | 传统 MPP,存算耦合 |
| 数据位置 | S3(属于你) | Redshift 自己的专用存储 |
| 计费 | 按扫描字节数 | 按节点 / 按小时 |
| 并发 | 默认 25(可调) | 50+(配合 Concurrency Scaling) |
| 性能 | 中(典型 4-30 秒) | 高(亚秒级到几秒) |
| 最适用于 | 数据湖临时查询 / ETL / ML 数据提取 | 高并发的 BI 看板 |
如何选择:我们的架构走的是数据湖路线,以 Athena 作为主引擎。如果你还需要高并发 BI(例如 100 名分析师同时刷新看板),可以在上层叠加 Redshift Spectrum(用 Redshift 的引擎查询 S3 外部表),实现「热数据在 Redshift,冷数据在 S3」的策略。
Athena vs. EMR Spark
| Athena | EMR Spark | |
|---|---|---|
| 编程方式 | 仅 SQL | SQL + Python + Scala + UDF |
| 复杂度 | 低 | 中到高 |
| 最适用于 | 简单的转换 / 聚合 / 任何 SQL 能表达的操作 | 重型 ETL / ML / 复杂逻辑 |
| 性能 | Trino 在中小数据集上很快 | Spark 在 TB 级以上数据集上更稳定 |
实践中:Athena CTAS 处理简单的 SQL 作业;EMR Serverless 处理复杂的 Spark 作业;两者共享同一个 Glue Catalog。
Lake Formation:数据治理与细粒度权限
为什么你需要它
Catalog 解决了「这是什么表」的问题,但**「谁能看到哪些列、哪些行」** 需要一个专门的权限层。
举例来说:
- ML 团队需要访问
ads_user_features,但绝不能看到 phone 或 id_card 列 - BI 分析师只能看到自己所在区域的数据
- 审计人员可以读取所有数据,但不能修改任何内容
传统数据仓库(如 Redshift)有自己的权限系统。但在数据分散于 S3 的数据湖中,你要如何管理访问权限?答案是 Lake Formation。
什么是 Lake Formation?
Lake Formation 是 AWS 构建在 Glue Catalog 之上的细粒度权限管理层:
- 行级安全(Row-Level Security)
- 列级安全(Column-Level Security)
- 数据脱敏 / 基于标签的访问控制(TBAC)
- 跨账户数据共享
工作原理
传统模型(仅 IAM):
IAM Role → S3 bucket policy → 这个 role 能读取 s3://bucket/path 吗?
Lake Formation 模型:
IAM Role
→ Glue Catalog(Table 概念)
→ Lake Formation 检查:这个 Role 对 ods_user 的特定列是否有 SELECT 权限?
→ 拒绝某些列 / 行,或整体拒绝
示例:列级权限
Lake Formation 的列级授权不是标准 ANSI SQL——它通过三种方式进行配置:
方式一:LF 控制台 / API(生产环境推荐)
在 Lake Formation 控制台中:Data permissions,Grant。选择 IAM Role + 表 + 勾选可见的列(include columns)或排除敏感列(exclude columns)。等价的 CLI:
aws lakeformation grant-permissions \
--principal DataLakePrincipalIdentifier=arn:aws:iam::123:role/data-science-role \
--permissions SELECT \
--resource '{
"TableWithColumns": {
"DatabaseName": "poc_social_layla",
"Name": "ads_user_features",
"ColumnNames": ["user_id","age","city","tags"]
}
}'
方式二:Athena 的 LF 风格 GRANT(引擎 v3 + 由 LF 管理的表)
GRANT SELECT (user_id, age, city, tags)
ON poc_social_layla.ads_user_features
TO PRINCIPAL 'arn:aws:iam::123:role/data-science-role';
注意 TO PRINCIPAL '<完整 ARN>'——这不是 PostgreSQL/Redshift 风格的 TO ROLE 'name'。
效果:
SELECT * FROM ads_user_features; -- Denied (includes phone/id_card)
SELECT user_id, age, tags FROM ads_user_features; -- OK
方式三:LF 基于标签的访问控制(LF-TBAC):给表/列打标签(例如 pii=true),然后按标签授予权限。对大型组织而言更具可扩展性。
常见坑
Lake Formation 的配置很复杂。常见的痛点:
- 权限叠加在 IAM 之上——调试时需要检查两层
- 由 Glue Crawler 自动创建的表可能不会继承 LF 权限
- 跨账户共享需要 Resource Links 才能生效
实用建议:在 POC 阶段,跳过 Lake Formation(使用粗粒度的 IAM)。等到进入生产环境时再启用它。
官方文档:Lake Formation
元数据 + 查询的全景图
┌─────────────────────────────────────────────────────┐
│ S3 物理数据层 │
│ warehouse/ods/event/dt=2026-05-10/*.parquet │
└──────────────────────┬──────────────────────────────┘
▲
│ 文件级访问
│
┌──────────────────────┴──────────────────────────────┐
│ Glue Data Catalog(元数据) │
│ poc_social_layla.ods_event │
│ schema、分区、location → s3://... │
└──────────────────────┬──────────────────────────────┘
▲
│ 获取表定义
│
┌──────────────────────┴──────────────────────────────┐
│ Lake Formation(权限层,可选) │
│ 针对每个 IAM Role:哪些列 / 行可见 │
└──────────────────────┬──────────────────────────────┘
▲
┌──────────────┼─────────────┬─────────────┐
│ │ │ │
Athena (SQL) EMR Spark SageMaker Redshift Spectrum
本章小结
| 概念 | 一句话总结 |
|---|---|
| Glue Data Catalog | 数据湖的中央表元数据存储,被所有引擎共享 |
| Glue Crawler | 扫描 S3 并自动建表(生产环境需谨慎使用) |
| Iceberg + Catalog | Catalog 存储的是指向 Iceberg metadata.json 的指针 |
| Athena | 无服务器 SQL 引擎,由 Trino 驱动,按扫描字节数计费 |
| Workgroup | Athena 的配置容器,用于成本治理和团队隔离 |
| Lake Formation | 列级 / 行级权限管理——在 IAM 之上的细粒度访问控制 |
参考资料
- AWS Glue Developer Guide — AWS Documentation
- Trino documentation — Trino
- Amazon Athena User Guide — AWS Documentation