oracle表增量同步到hive分区表

本文介绍了一种使用Shell脚本实现从Oracle数据库到Hive数据仓库的数据迁移方法。脚本接收服务器IP、数据库名、表名等参数,通过sqoop工具导入数据,再利用Hive SQL进行数据转换和分区,最后触发Impala刷新,确保数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文以shell脚本,通过传参的的形式,将服务器ip,oracle的库名表名以及作为分区字段的字段名称,hive的库名,表名作为参数传入,这样可以做到灵活变更,提高通用性与方便性,通过定时器调度此脚本即可。

脚本包含三步:

   一:通过sqoop将oracle数据导入到hive临时表,临时表需创建,无分区表

   二:将hive临时表数据insert到hive正式表,以传入的分区字段作为分区,此脚本中分区有 年xxxx,月xxxx-xx,日xxxx-xx-xx

   三:因为我有用到impala,所以在第三步加上了impala刷新操作,如不刷新,impala将识别不到新增hive数据   

#!/bin/bash
#

# import table from oracle into hive

nargs=$#
echo "argument num: $nargs "

today=`date +%Y-%m-%d`
one_day=`date +%Y-%m-%d -d'-1 day'`
coll_db=''
coll_tab=''
coll_host_ip=''
coll_host_port=1521
coll_tab_username=''
coll_tab_passwd=''

hive_db=''
hive_tab=''
#hive_tab_cols=''
hive_map_cols=''

start_dt=''
end_dt=''

pt_col='' 

/usr/bin/kinit -kt /opt/yarn.keytab yarn

# argument parse
argParse()
{
    echo "argument num: $nargs "

    for ag in $@
    do
    #    echo $ag
        arg_key=${ag%=*}
        arg_val=${ag#*=}
#        echo "${ag%=*}--- ${ag#*=}"        
#        echo "$arg_key---- $arg_val"
        case ${arg_key} in
            "coll_host_ip")     coll_host_ip=$arg_val    ;;
            "coll_db")         coll_db=$arg_val    ;;
            "coll_tab")         coll_tab=$arg_val    ;;
            "hive_db")         hive_db=$arg_val    ;;
            "hive_tab")         hive_tab=$arg_val    ;;
            #"hive_tab_cols")     hive_tab_cols=$arg_val    ;;
            "hive_map_cols")     hive_map_cols=$arg_val    ;;
            "start_dt")         start_dt=$arg_val    ;;
            "end_dt")         end_dt=$arg_val    ;;
            "pt_col")         pt_col=$arg_val    ;;
        esac
    done
}

# parse the arguments key:value paire
argParse $@
# pring argument
printArgs()
{
    echo "coll_host_ip:$coll_host_ip"
    echo "coll_db:$coll_db"
    echo "coll_tab:$coll_tab"
    echo "hive_db:$hive_db"
    echo "hive_tab:$hive_tab"
    #echo "hive_tab_cols:$hive_tab_cols"
    echo "hive_map_cols:$hive_map_cols"
    echo "start_dt:$start_dt"
    echo "end_dt:$end_dt"
    echo "pt_col:$pt_col"
        echo "one_day:$one_day"
        echo "today:$today"
}

# print the value of argument
printArgs

# sqoop import table of mysql to hive tmp table
sqoopImpTempTab()
{
    echo  "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ [`date +\"%F %T\"`] sqoop import start @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ "
        if [ -n "${hive_map_cols}" ]
        then
        sqoop import -Dorg.apache.sqoop.splitter.allow_text_splitter=true -Dmapreduce.job.queuename=bf_yarn_pool.production \
                        --connect jdbc:oracle:thin:@$coll_host_ip:$coll_host_port/$coll_db \
                        --table $coll_tab --username $coll_tab_username --password $coll_tab_passwd \
                        --delete-target-dir \
                    --hive-import --hive-overwrite --hive-database tmp_${hive_db} --hive-table tmp_${hive_tab} --hive-drop-import-delims -m 1 \
                    --where "${pt_col} >=to_date('${one_day}','yyyy-mm-dd') and ${pt_col}<to_date('${today}','yyyy-mm-dd')" --fields-terminated-by '\001' \
            --split-by ${hive_map_cols} \
                    --null-string '\\N' --null-non-string '\\N' 
        else
        sqoop import -Dorg.apache.sqoop.splitter.allow_text_splitter=true -Dmapreduce.job.queuename=bf_yarn_pool.production \
                        --connect jdbc:oracle:thin:@$coll_host_ip:$coll_host_port/$coll_db \
                    --table $coll_tab --username $coll_tab_username --password $coll_tab_passwd \
            --delete-target-dir \
                        --hive-import --hive-overwrite --hive-database tmp_${hive_db} --hive-table tmp_${hive_tab} --hive-drop-import-delims -m 1 \
                        --where "${pt_col} >=to_date('${one_day}','yyyy-mm-dd') and ${pt_col}<to_date('${today}','yyyy-mm-dd')" --fields-terminated-by '\001' \
                        --null-string '\\N' --null-non-string '\\N' #&> /dev/null 

        fi
        RET=$?
        if [ $RET -eq 0 ]; then
                echo "`date +\"%F %T\"` [INFO] sqoop import database:$hive_db table:temp_$hive_tab successfully."
        else
                echo "`date +\"%F %T\"` [ERROR] sqoop import database:$hive_db table:temp_$hive_tab error."
                exit 5
        fi
        echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ [`date +\"%F %T\"`] sqoop import end @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ "

}
sqoopImpTempTab

# store tmp table to hive rcfile table
hiveStoreAsRc()
{

    #pt_col=create_time
        echo '---------------------------------------------------------- hive store as rcfile start  -------------------------------------------------------------------------------------'

    hsql="use ${hive_db};set hive.exec.dynamic.partition=true;set hive.exec.dynamic.partition.mode=nonstrict;
                set mapreduce.map.memory.mb=15000;set mapreduce.reduce.memory.mb=15000; set hive.merge.mapredfiles=true;set hive.exec.max.created.files=100000;
                SET hive.exec.max.dynamic.partitions=100000;SET hive.exec.max.dynamic.partitions.pernode=100000;from tmp_${hive_db}.tmp_${hive_tab} \
        INSERT OVERWRITE TABLE ${hive_db}.${hive_tab} PARTITION(pk_year,pk_month,pk_day) select *,substr(${pt_col}, 1, 4),substr(${pt_col}, 1, 7),substr(${pt_col}, 1, 10) \
        where ${pt_col} >='${one_day}' and ${pt_col}<'${today}' "

    #phsql=$hsql" INSERT INTO TABLE ${hive_db}.${hive_tab} PARTITION(partition_key='${sdt:0:7}') select $hive_tab_cols where $pt_col > '${sdt:0:7}';"    
    echo "#################### hsql: $hsql"
    #hive -S -e "${hsql}"
    beeline --hiveconf mapreduce.job.queuename=bf_yarn_pool.production --silent=true --showHeader=false --showWarnings=false -u 'jdbc:hive2://localhost:10000/default;' -n yarn -p *******  -e "${hsql}"    

    RET=$?
    if [ $RET -eq 0 ]; then
            echo "`date +\"%F %T\"` [INFO] ${hive_db}.${hive_tab}  store successfully." 
                #exit 0
    else
               echo "`date +\"%F %T\"` [ERROR] ${hive_db}.${hive_tab}  store failure." 
               exit 5
    fi
        echo '---------------------------------------------------------- hive store as rcfile end  -------------------------------------------------------------------------------------'
}

hiveStoreAsRc

# impala table refresh
impTabRefrsh()
{
    echo '********************************************************** impala refresh table start *****************************************************************************************'    
        beeline --silent=true --showHeader=false --showWarnings=false -u 'jdbc:hive2://localhost:21050/default;' -n yarn -p ******* -e "refresh ${hive_db}.${hive_tab}"

    RET=$?

    if [ ${RET} -eq 0 ]; then
        echo "`date +\"%F %T\"` [INFO] impala:refresh ${hive_db}.${hive_tab} success!"
        exit 0
    else    
        echo "`date +\"%F %T\"` [ERROR] impala:refresh ${hive_db}.${hive_tab} failure!"
        exit 5
    fi    
    echo '********************************************************** impala refresh table end *****************************************************************************************'    
}

impTabRefrsh 
 

### SeaTunnel Oracle 数据抽取到 Hive 的实现方案 #### 背景说明 在实际的数据处理场景中,Oracle 数据库作为传统关系型数据库被广泛应用于企业核心业务系统。然而,随着大数据技术的发展,越来越多的企业希望将 Oracle 中的数据迁移到分布式存储系统(如 Hadoop 生态中的 Hive),以便更好地支持大规模数据分析和挖掘。 SeaTunnel 是一款强大的流批一体数据集成工具,能够高效完成不同数据源之间的数据同步任务。以下是使用 SeaTunnel 将 Oracle 数据抽取并加载到 Hive 的具体实现方案[^1]。 --- #### 技术选型与原理概述 为了实现从 Oracle 提取数据并加载到 Hive,可以选择以下两种主要方式: 1. **CDC(Change Data Capture)模式** 使用 CDC 工具捕获 Oracle 数据的变化日志,并将其写入消息队列(如 Kafka)。随后利用 SeaTunnel 读取消息队列中的变更记录并将这些数据实时写入 Hive 中。 2. **批量导出模式** 如果不需要实时性,可以通过触发器或 SQL 查询的方式定期从 Oracle 导出全量或增量数据,再借助 SeaTunnel 批量导入到 Hive。 这两种方式各有优劣,需根据具体的业务需求和技术环境选择合适的方案。 --- #### 方案一:基于 CDC 和 SeaTunnel 的实时同步 ##### 步骤描述 1. 配置 Oracle 的逻辑日志功能(LogMiner 或 GoldenGate 等),启用 CDC 功能以捕获数据变化。 2. 将捕获的日志数据发送至消息中间件(如 Apache Kafka)。 3. 编写 SeaTunnel 作业配置文件,指定输入源为 Kafka,输出目标为 Hive。 4. 启动 SeaTunnel 作业,消费 Kafka 中的消息并解析后写入 Hive 。 ##### 示例代码 以下是一个典型的 SeaTunnel 作业配置文件示例,用于从 Kafka 消费数据并写入 Hive: ```yaml env { execution.parallelism = 1 } source { kafka { topic = "oracle-changes" brokers = "localhost:9092" group.id = "seatunnel-group" format = "json" } } transform {} sink { hive { database-name = "default" table-name = "student" fields = ["id", "name"] partition-by = [] pre-insert-sql = "" post-insert-sql = "" } } ``` 此配置定义了一个简单的 ETL 流程,其中 Kafka 是数据源,Hive 是目标存储系统。 --- #### 方案二:基于批量查询的离线同步 ##### 步骤描述 1. 创建一个临时或视图,用于存储待迁移的 Oracle 数据。 2. 构建 SeaTunnel 作业配置文件,设置输入源为 Oracle 数据库,输出为目标 Hive 。 3. 运行 SeaTunnel 作业,执行一次性或周期性的数据迁移操作。 ##### 示例代码 下面展示了一种通过 JDBC 接口连接 Oracle 并将数据写入 Hive 的配置方法: ```yaml env { execution.parallelism = 1 } source { jdbc { driver-name = "oracle.jdbc.driver.OracleDriver" url = "jdbc:oracle:thin:@//<host>:<port>/<service_name>" username = "<username>" password = "<password>" query = "SELECT * FROM student WHERE last_update_time >= ? AND last_update_time < ?" split-query = "SELECT MIN(last_update_time), MAX(last_update_time) FROM student" fetch-size = 1000 } } transform {} sink { hive { database-name = "default" table-name = "student" fields = ["id", "name"] partition-by = [] pre-insert-sql = "" post-insert-sql = "" } } ``` 在此配置中,`query` 参数指定了从 Oracle 获取数据的具体 SQL 语句;`split-query` 可用于分片处理大数据,提高并发性能。 --- #### 关键注意事项 1. **字段映射问题** 在将 JSON 类型或其他复杂结构化数据从 Oracle 移植到 Hive 时,可能需要调整字段类型。例如,JSON 字段应转换为 `VARCHAR2` 类型,并在外围加上单引号包裹[^4]。 2. **时间戳一致性** 确保 OracleHive 时间戳格式一致,必要时可通过 UDF 函数进行格式转换。 3. **分区策略优化** 对于 Hive 设计,建议合理规划分区字段(如日期维度),从而提升后续查询效率。 4. **错误重试机制** 在生产环境中部署 SeaTunnel 作业时,务必开启失败重试选项,保障数据传输稳定性。 --- #### 性能对比分析 | 特性 | CDC 实时同步 | 批量离线同步 | |--------------------|----------------------------------|-----------------------------| | 实时性 | 支持毫秒级延迟 | 周期性运行,延迟较高 | | 开发成本 | 较高,涉及日志解析 | 较低 | | 数据准确性 | 更加精确 | 存在潜在丢失风险 | | 应用场景 | 需求高频更新的小规模数据 | 大规模静态数据迁移 | 根据以上特性对比,可进一步评估哪种方案更适合当前项目背景。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值