一、概述
阿里云 MaxCompute(原 ODPS) 是一种大数据计算服务,支持大规模数据存储和分布式计算。本文档以"每天定时查询 T-1 库存快照"为场景,详细说明如何利用 MaxCompute 的 SQL 能力和 DataWorks 的调度功能实现自动化任务。
二、核心概念
|----------------------|-----------------------------------------------------|
| 概念 | 说明 |
| MaxCompute(ODPS) | 阿里云提供的大数据计算服务,支持 SQL 查询、MapReduce、机器学习等。 |
| DataWorks | 阿里云数据开发平台,用于调度、监控和管理 MaxCompute 任务。 |
| 分区表 | 按日期或其他字段分区的表,提升查询效率。例如:date_partition='20231001'。 |
| 内置变量 | 如 ${bdp.system.bizdate},表示当前任务的业务日期(格式:YYYYMMDD)。 |
| 调度任务 | 在 DataWorks 中配置的周期性任务(如每天凌晨执行)。 |
三、使用场景
需求:每天定时查询库存快照表中 T-1(前一日)的数据,并将结果保存到目标表中,供下游任务使用。
四、操作步骤
1. 表结构设计
1.1 源表(库存快照表)
-- original_inventory_snapshot 表结构
-- 存储每日的库存快照数据
CREATE TABLE IF NOT EXISTS original_inventory_snapshot (
product_id STRING COMMENT '商品ID',
inventory_count BIGINT COMMENT '库存数量',
snapshot_time DATETIME COMMENT '快照时间'
)
PARTITIONED BY (date_partition STRING); -- 按日期分区
1.2 目标表(存储查询结果)
-- target_inventory_daily 表结构
-- 存储每日查询的 T-1 数据
CREATE TABLE IF NOT EXISTS target_inventory_daily (
product_id STRING,
inventory_count BIGINT,
snapshot_time DATETIME
)
PARTITIONED BY (date_partition STRING);
1.3 为什么要目标表
- 任务调度的本质
MaxCompute 的调度任务(如 DataWorks)本质上是作业流,需要有明确的输入和输出。
-
- 输入:源表(如
dwd_inventory_snapshot) - 输出:目标表(如
target_inventory_daily)
如果没有输出表,任务执行后结果无法保存,后续无法使用这些数据。
- 输入:源表(如
- 数据持久化需求
如果仅"直接查询"现有快照表(如dwd_inventory_snapshot),查询结果会临时存在于内存或日志中,无法长期保存。创建目标表可以确保:
-
- 数据被持久化存储,供后续分析、报表或下游任务使用。
- 支持历史数据追溯(例如查看某天的 T-1 快照)。
- 分区管理
MaxCompute 的表通常按日期分区(如date_partition='20231001')。通过将结果写入目标表的特定分区,可以:
-
- 避免数据覆盖(如使用
INSERT OVERWRITE)。 - 实现数据版本控制(例如每天一个分区)。
- 避免数据覆盖(如使用
2. 编写 SQL 查询语句
-- 将 T-1 的数据写入目标表的当前日期分区
INSERT OVERWRITE TABLE target_inventory_daily PARTITION (date_partition='${bdp.system.bizdate}')
SELECT
product_id,
inventory_count,
snapshot_time
FROM
original_inventory_snapshot
WHERE
date_partition = DATE_FORMAT(DATE_SUB('${bdp.system.bizdate}', 1), '%Y%m%d');
关键点
${bdp.system.bizdate}:当前任务的业务日期(如20231001)。DATE_SUB(..., 1):计算 T-1 的日期(如20231001→20230930)。DATE_FORMAT(..., '%Y%m%d'):将日期格式化为YYYYMMDD,与分区字段一致。
3. 在 DataWorks 中配置调度任务
3.1 创建任务
- 登录 DataWorks 控制台。
- 新建一个 MaxCompute SQL 任务。
- 将上述 SQL 脚本粘贴到任务编辑器中。
3.2 配置调度参数
|----------|------------------------------------------------------------|
| 参数 | 配置值 |
| 调度周期 | 按天执行(如每天凌晨 1 点)。 |
| 依赖关系 | 确保源表 original_inventory_snapshot 的 T-1 数据已生成(如凌晨 0 点同步)。 |
| 输出表 | target_inventory_daily,并指定分区字段 date_partition。 |
| 报警规则 | 配置任务失败时的通知方式(如邮件、钉钉)。 |
4. 验证任务
4.1 手动运行测试
-
在 DataWorks 中手动执行任务,验证 SQL 是否正确。
-
检查目标表
target_inventory_daily是否生成 T-1 数据:SELECT * FROM target_inventory_daily WHERE date_partition='20231001';
4.2 自动化运行
- 任务首次运行后,后续会按调度时间自动执行。
五、注意事项
1. 数据延迟处理
- 问题 :源表
original_inventory_snapshot的 T-1 数据可能在凌晨 0 点才生成。 - 解决方案:
-
- 将调度任务设置为 凌晨 2 点 执行。
- 在 SQL 中添加等待逻辑(如
SLEEP(3600)),但需谨慎使用。
2. 分区字段格式
-
问题 :
date_partition字段格式为YYYYMMDD,需与DATE_SUB结果匹配。 -
解决方案:
WHERE date_partition = DATE_FORMAT(DATE_SUB('${bdp.system.bizdate}', 1), '%Y%m%d');
3. 资源与成本
- 建议:
-
- 定期清理旧分区数据(如保留 30 天)。
- 使用
INSERT OVERWRITE避免重复插入。
六、扩展场景
1. 动态分区查询
如果源表未按日期分区,可直接按时间字段过滤:
-- 按 snapshot_time 过滤 T-1 数据
INSERT OVERWRITE TABLE target_inventory_daily PARTITION (date_partition='${bdp.system.bizdate}')
SELECT
product_id,
inventory_count,
snapshot_time
FROM
original_inventory_snapshot
WHERE
DATE(snapshot_time) = DATE_SUB('${bdp.system.bizdate}', 1);
2. 多表关联
若需关联其他表(如商品信息表),可扩展 SQL:
-- 关联商品表获取商品名称
SELECT
a.product_id,
b.product_name,
a.inventory_count
FROM
original_inventory_snapshot a
JOIN
dim_product b ON a.product_id = b.product_id
WHERE
a.date_partition = DATE_FORMAT(DATE_SUB('${bdp.system.bizdate}', 1), '%Y%m%d');
七、附录
1. 常用函数参考
|--------------------------|-------------------------|
| 函数 | 功能 |
| DATE_SUB(date, n) | 计算日期前 N 天。 |
| DATE_FORMAT(date, fmt) | 格式化日期为指定格式(如 %Y%m%d)。 |
| INSERT OVERWRITE | 覆盖写入目标表的指定分区。 |
2. 调度时间示例
- 每日凌晨 1 点 :
0 1 * * * - 每周一凌晨 2 点 :
0 2 * * 1
通过以上步骤和注意事项,可高效实现每天定时查询 T-1 库存快照的需求,确保数据处理自动化与准确性。