ODPS insert overwrite/into

本文详细解释了Hive SQL中INSERT OVERWRITE与INSERT INTO的区别及用法。INSERT INTO用于向表或分区追加数据,而INSERT OVERWRITE则会先清空目标再插入新数据。

INSERT OVERWRITE/INTO
语法:
INSERT OVERWRITE|INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
select_statement
FROM from_statement;

insert into 是向表或分区中追加数据,而insert overwrite则先清空表或者分区,然后再插入数据

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26613085/viewspace-1327424/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26613085/viewspace-1327424/

ODPSSQL(即阿里云 MaxCompute SQL)中,**动态分区**是一种非常重要的功能,用于将数据根据某列的值自动写入不同的物理分区中。它类似于 Hive 中的 `INSERT ... SELECT ...` 动态分区机制。 --- ### ✅ 什么是动态分区? 动态分区允许你在 `INSERT INTO TABLE ... SELECT` 语句中,根据 SELECT 查询结果中的某一列(或几列)的值,**自动决定数据写入哪个分区**,而不需要为每个分区单独写一条 INSERT 语句。 --- ### 🔧 使用动态分区的基本语法 ```sql SET odps.sql.allow.dynamic.partition=true; -- 必须开启动态分区开关 INSERT OVERWRITE|INTO TABLE table_name PARTITION (partition_col) SELECT select_list_without_partition_col FROM source_table [DISTRIBUTE BY partition_col]; -- 可选,但推荐使用 ``` > 注意:从 MaxCompute 2.0 开始支持动态分区,但需要显式开启参数。 --- ### 📌 示例说明 假设你有一个日志表 `logs_raw`,结构如下: ```sql CREATE TABLE logs_raw ( user_id STRING, action STRING, server_time STRING -- 格式: '2025-09-22 13:00:01' ); ``` 你想按日期(`dt`) 分区插入到目标表 `logs_partitioned` 中: ```sql CREATE TABLE logs_partitioned ( user_id STRING, action STRING ) PARTITIONED BY (dt STRING); -- 分区字段 dt 表示 YYYYMMDD ``` 现在你想把 `server_time` 转成 `YYYYMMDD` 格式,并作为分区键动态写入: ```sql -- 启用动态分区(关键!) SET odps.sql.allow.dynamic.partition=true; INSERT OVERWRITE TABLE logs_partitioned PARTITION (dt) SELECT user_id, action, REPLACE(SUBSTR(server_time, 1, 10), '-', '') AS dt -- 生成分区值 FROM logs_raw WHERE server_time IS NOT NULL AND LENGTH(server_time) >= 10; ``` --- ### ✅ 关键点解释: | 要素 | 说明 | |------|------| | `SET odps.sql.allow.dynamic.partition=true;` | **必须设置**,否则会报错不支持动态分区 | | `PARTITION (dt)` 在 INSERT 子句中 | 声明这是动态分区写入 | | `dt` 出现在 SELECT 的最后 | SELECT 列表中最后一个字段是分区列的值 | | 不要在 SELECT 中包含其他分区列 | 分区列不能出现在非分区位置 | > ⚠️ 如果有多个分区列,比如 `(dt STRING, region STRING)`,则: > > ```sql > INSERT INTO TABLE t PARTITION (dt, region) > SELECT ..., dt_col, region_col FROM src; > ``` > 最后两列必须对应 `dt_col` 和 `region_col` --- ### 💡 推荐使用 `DISTRIBUTE BY` 优化性能 为了防止数据倾斜和提升执行效率,建议对分区列进行分发: ```sql INSERT OVERWRITE TABLE logs_partitioned PARTITION (dt) SELECT user_id, action, REPLACE(SUBSTR(server_time, 1, 10), '-', '') AS dt FROM logs_raw WHERE server_time IS NOT NULL DISTRIBUTE BY dt; -- 将相同 dt 的数据发送到同一个 reducer ``` 这有助于减少 shuffle 并提高分区写入效率。 --- ### 🛑 常见错误与注意事项 | 错误 | 原因 | 解决方法 | |------|------|----------| | `Dynamic partition is not enabled` | 未开启动态分区 | 加上 `SET odps.sql.allow.dynamic.partition=true;` | | 分区列出现在 SELECT 中间位置 | 顺序错误 | 分区列必须放在 SELECT 最后 | | 写成了 `PARTITION (dt='xxx')` | 静态分区写法 | 改为 `PARTITION (dt)` 才是动态 | | 分区字段类型不匹配 | 如定义为 BIGINT,传入 STRING | 确保类型一致 | --- ### ✅ 动态分区 vs 静态分区对比 | 特性 | 静态分区 | 动态分区 | |------|----------|-----------| | 是否需指定分区名 | 是(如 `dt='20250922'`) | 否,由数据决定 | | 写多分区是否方便 | 每个分区都要写一条 INSERT | 一条 SQL 完成多个分区写入 | | 性能 | 简单场景快 | 大量分区更高效 | | 是否需要设置参数 | 否 | 是(`allow.dynamic.partition`) | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值