第二十三讲:云数据仓库ETL——Redshift、BigQuery、Snowflake与云原生工具
说实话,几年前我还在跟传统数仓死磕的时候,压根没想到云数据仓库会发展得这么快。现在你随便问一个做ETL的同行,大概率都在跟这三家打交道:AWS Redshift、Google BigQuery、Snowflake。再加上配套的云原生ETL工具,整个生态已经相当成熟了。
这一讲,我就把这几大云数仓的核心玩法,以及它们对应的ETL工具,给你掰开揉碎了讲清楚。嗯,都是我在实际项目中踩过的坑和总结的经验。
一、三大云数据仓库的ETL差异
先看一张图,帮你快速建立整体认知:
二、AWS Redshift:传统数仓的云上延续
Redshift给我的感觉,就像把Oracle或Teradata搬到了云上。它基于PostgreSQL 8.x内核改造,但存储引擎完全重写成了列式存储。
2.1 数据加载方式
我个人习惯用COPY命令从S3加载数据。这是最快的方式,没有之一。
-- 从S3加载CSV数据到Redshift
COPY sales_data
FROM 's3://my-bucket/sales/2024/'
IAM_ROLE 'arn:aws:iam::123456789:role/RedshiftS3ReadOnly'
CSV
IGNOREHEADER 1
DELIMITER ','
REGION 'us-east-1';
2.2 排序键与分布键
Redshift的ETL性能,很大程度上取决于表设计。说白了,排序键和分布键选对了,查询快得像开挂;选错了,慢到你想砸键盘。
-- 创建表时指定排序键和分布键
CREATE TABLE orders (
order_id BIGINT,
customer_id INT,
order_date DATE,
amount DECIMAL(10,2)
)
DISTKEY(customer_id)
SORTKEY(order_date);
三、Google BigQuery:无服务器的大数据引擎
BigQuery跟Redshift完全是两种思路。它不需要你管理集群,也不关心节点数量。你只管写SQL,它自动分配计算资源。
3.1 外部表与分区
BigQuery支持直接查询GCS(Google Cloud Storage)上的文件,这叫外部表。我经常用它做数据湖的临时查询。
-- 创建外部表指向GCS上的Parquet文件
CREATE EXTERNAL TABLE project.dataset.external_sales
OPTIONS (
format = 'PARQUET',
uris = ['gs://my-bucket/sales/*.parquet']
);
-- 查询外部表
SELECT region, SUM(amount) as total_sales
FROM project.dataset.external_sales
WHERE order_date >= '2024-01-01'
GROUP BY region;
3.2 分区与聚簇
BigQuery按扫描量收费,所以减少扫描数据量就是省钱。分区和聚簇是两大法宝。
-- 创建分区表,按日期分区
CREATE TABLE project.dataset.sales_partitioned
PARTITION BY DATE(order_date)
CLUSTER BY region
AS
SELECT * FROM source_table;
我的经验: 有一次客户跑月度报表,没做分区,每次扫描2TB数据,一个月花了3000多刀。加上分区后,每次只扫50GB,费用降到200刀。你想想看,这差距有多大。
四、Snowflake:计算与存储分离的典范
Snowflake是我个人最喜欢的云数仓。它把计算和存储彻底分开,你可以独立扩缩计算资源,存储则按实际使用量付费。
4.1 Virtual Warehouse与自动挂起
Snowflake的ETL核心是Virtual Warehouse(虚拟仓库)。你可以为不同的ETL任务创建不同大小的仓库,用完自动挂起,不产生额外费用。
-- 创建虚拟仓库,用于ETL任务
CREATE WAREHOUSE etl_wh
WITH
WAREHOUSE_SIZE = 'MEDIUM'
AUTO_SUSPEND = 300 -- 5分钟无活动自动挂起
AUTO_RESUME = TRUE; -- 有查询时自动恢复
-- 使用仓库执行ETL
USE WAREHOUSE etl_wh;
-- 从外部Stage加载数据
COPY INTO sales_table
FROM @my_stage/sales/
FILE_FORMAT = (TYPE = CSV FIELD_OPTIONALLY_ENCLOSED_BY = '"');
4.2 Time Travel与零拷贝克隆
Snowflake有个很酷的功能叫Time Travel,可以查询过去任意时间点的数据。我在做数据回溯时经常用到。
-- 查询30分钟前的表状态
SELECT * FROM sales_table
AT (TIMESTAMP => DATEADD(minute, -30, CURRENT_TIMESTAMP));
-- 零拷贝克隆,用于测试环境
CREATE TABLE sales_dev CLONE sales_table;
五、云原生ETL工具
光有数仓还不够,你得有工具把数据搬进去。下面这三款工具,我基本每天都在用。
5.1 AWS Glue:无服务器ETL
Glue是AWS的托管ETL服务,底层基于Apache Spark。你不需要管理Spark集群,Glue自动帮你搞定。
# Glue ETL脚本示例(Python)
import sys
from awsglue.transforms import *
from awsglue.context import GlueContext
from pyspark.context import SparkContext
sc = SparkContext()
glueContext = GlueContext(sc)
# 从S3读取数据
datasource = glueContext.create_dynamic_frame.from_options(
connection_type="s3",
connection_options={"paths": ["s3://my-bucket/input/"]},
format="json"
)
# 数据转换
transformed = ApplyMapping.apply(
frame=datasource,
mappings=[
("id", "string", "id", "string"),
("price", "double", "amount", "decimal"),
("timestamp", "string", "event_time", "timestamp")
]
)
# 写入Redshift
glueContext.write_dynamic_frame.from_jdbc_conf(
frame=transformed,
catalog_connection="redshift-conn",
connection_options={
"dbtable": "public.sales",
"database": "dev"
}
)
5.2 Google Dataflow:基于Apache Beam
Dataflow是GCP的流批一体ETL工具。它基于Apache Beam,一套代码可以同时跑批处理和流处理。
// Dataflow批处理示例(Java)
public class BatchETL {
public static void main(String[] args) {
Pipeline p = Pipeline.create(
PipelineOptionsFactory.fromArgs(args).create()
);
// 从GCS读取
p.apply("ReadFromGCS", TextIO.read().from("gs://my-bucket/input/*.csv"))
.apply("ParseCSV", ParDo.of(new DoFn<String, KV<String, Double>>() {
@ProcessElement
public void processElement(ProcessContext c) {
String[] fields = c.element().split(",");
c.output(KV.of(fields[0], Double.parseDouble(fields[1])));
}
}))
.apply("SumByKey", Sum.doublesPerKey())
.apply("WriteToBigQuery", BigQueryIO.writeTableRows()
.to("project:dataset.sales_summary")
.withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_APPEND));
p.run();
}
}
5.3 Snowpipe:Snowflake的自动加载
Snowpipe是Snowflake的自动数据加载服务。你只要把文件放到云存储上,Snowpipe自动检测并加载到表中。
-- 创建Pipe,自动加载S3上的数据
CREATE PIPE my_pipe
AUTO_INGEST = TRUE
AS
COPY INTO sales_table
FROM @my_s3_stage
FILE_FORMAT = (TYPE = CSV);
-- 查看Pipe状态
SELECT SYSTEM$PIPE_STATUS('my_pipe');
六、选型建议
说了这么多,到底怎么选?我根据项目经验给你列个参考:
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 已有AWS生态 | Redshift + Glue | 集成度高,S3/RDS等无缝对接 |
| 大数据分析为主 | BigQuery + Dataflow | 无服务器,按量付费,适合Ad-hoc查询 |
| 多云或混合云 | Snowflake + Snowpipe | 跨云支持好,计算存储分离 |
| 实时流处理 | Dataflow(Beam) | 流批一体,延迟低 |
嗯,云数据仓库的ETL就讲到这里。说白了,没有银弹,只有最适合你业务场景的方案。我建议你每个都上手试一下,跑几个真实任务,感受一下差异。实践出真知嘛。
公众号:蓝海资料掘金营,微信deep3321