在 Hive 中实现MERGE即 UPSERT存在则更新不存在则插入主要有以下几种方式具体选择取决于你的Hive 版本和表类型。1. 原生 MERGE 语句推荐Hive 2.2 / 3.x从 Hive 2.2 开始引入了标准的 SQLMERGE INTO语法但前提是目标表必须是 ACID 事务表。前置条件Hive 版本 2.2目标表必须是ORC 格式分桶表事务表需开启相关配置-- 开启ACID事务支持SEThive.support.concurrencytrue;SEThive.enforce.bucketingtrue;SEThive.exec.dynamic.partition.modenonstrict;SEThive.txn.managerorg.apache.hadoop.hive.ql.lockmgr.DbTxnManager;建表示例CREATETABLEtarget_table(idINT,name STRING,amountDECIMAL(10,2))CLUSTEREDBY(id)INTO4BUCKETS STOREDASORC TBLPROPERTIES(transactionaltrue);MERGE 语法MERGEINTOtarget_table tUSINGsource_table sONt.ids.idWHENMATCHEDANDs.is_deletedtrueTHENDELETEWHENMATCHEDTHENUPDATESETt.names.name,t.amounts.amountWHENNOTMATCHEDTHENINSERTVALUES(s.id,s.name,s.amount);⚠️注意ACID 表的MERGE底层会产生 delta 文件需要定期执行ALTER TABLE ... COMPACT进行合并压缩否则查询性能会严重下降。2. INSERT OVERWRITE 模拟 MERGE最通用适用于非事务表对于普通外部表/内部表Parquet、TextFile 等无法使用原生 MERGE通常用INSERT OVERWRITEFULL OUTER JOIN或LEFT JOIN来模拟。这是生产环境中最常见的做法。核心思路将源表和目标表做关联通过COALESCE/CASE WHEN决定最终取值然后覆盖写回目标表或新分区。INSERTOVERWRITETABLEtarget_tablePARTITION(dt2026-06-30)SELECTCOALESCE(s.id,t.id)ASid,-- 匹配到则取源表值未匹配到保留目标表原值CASEWHENs.idISNOTNULLTHENs.nameELSEt.nameENDASname,CASEWHENs.idISNOTNULLTHENs.amountELSEt.amountENDASamountFROMtarget_table tFULLOUTERJOINsource_table sONt.ids.idWHEREt.dt2026-06-30;-- 只处理目标分区变体仅处理增量数据性能优化如果源表只是增量数据可以先 UNION 再 GROUP BY 去重INSERTOVERWRITETABLEtarget_tablePARTITION(dt2026-06-30)SELECTid,name,amountFROM(SELECTid,name,amount,ROW_NUMBER()OVER(PARTITIONBYidORDERBYupdate_timeDESC)ASrnFROM(SELECT*FROMtarget_tableWHEREdt2026-06-30UNIONALLSELECT*FROMsource_table)combined)rankedWHERErn1;优点不依赖 ACID兼容所有存储格式和 Hive 版本。 缺点每次都是全量重写整个分区数据量大时 I/O 开销高。3. 各方案对比总结维度原生 MERGE (ACID)INSERT OVERWRITE 模拟Hive 版本要求≥ 2.2任意版本表格式要求必须 ORC 分桶 事务属性任意格式Parquet/ORC/CSV等写入方式增量写入 delta 文件全量覆盖分区DELETE 支持✅ 原生支持❌ 需额外过滤逻辑查询性能需 Compact 后才好写完即可查无额外维护并发安全✅ 有锁机制❌ 无锁需调度层保证适用场景实时/准实时 CDC 入仓离线 T1 批量 ETL运维复杂度高需管理 Compaction低 最佳实践建议离线数仓首选方案 2大多数离线 ETL 场景不需要 ACID 特性INSERT OVERWRITE更稳定、更易排查问题且与 Spark/Flink 生态兼容性更好。CDC / 实时同步选方案 1如果需要频繁小批量 UPSERT 且对延迟敏感使用 ACID 表的MERGE但务必配置自动 Compaction 或定时手动触发。考虑替代引擎如果 MERGE 是高频操作建议评估Apache Iceberg / Hudi / Delta Lake等数据湖格式它们原生支持高效 Upsert/Merge且无需 Hive ACID 的 Compaction 负担已成为现代数据架构的主流选择。避免大表全量 OVERWRITE如果目标表非常大且只有少量变更可考虑按主键范围拆分为多个子任务并行处理或使用分桶表配合INSERT INTO追加 读取时去重的策略。