sqoop import将Oracle数据加载至hive,数据量变少,只能导入一个mapper的数据量

sqoop脚本如下:

bash 复制代码
sqoop import -D mapred.job.queue.name=highway \
-D mapreduce.map.memory.mb=4096 \
-D mapreduce.map.java.opts=-Xmx3072m \
--connect "jdbc:oracle:thin:@//1.2.3.4.5:61521/LZY2" \
--username root \
--password '123456' \
--query "SELECT 
ZBDM
,ZBMC
,TO_CHAR(TJSJ, 'YYYY') AS tjsj_year
,TO_CHAR(TJSJ, 'MM') AS tjsj_month
,TO_CHAR(TJSJ, 'DD') AS tjsj_day
,TO_CHAR(TJSJ, 'YYYY-MM-DD HH24:MI:SS') AS TJSJ
......
,TO_CHAR(INPUTTIME, 'YYYY-MM-DD HH24:MI:SS') AS INPUTTIME
,UUID
,TO_CHAR(INSERTTIME, 'YYYY-MM-DD HH24:MI:SS') AS INSERTTIME
FROM LZJHGX.T_JSZX_TF_KJ2_LL
WHERE TO_CHAR(TJSJ , 'YYYY-MM-DD') < TO_CHAR(SYSDATE,'YYYY-MM-DD') AND \$CONDITIONS" \
--split-by ROWNUM \
--boundary-query "select 1 as MIN , sum(1) as MAX from LZJHGX.T_JSZX_TF_KJ2_LL" \
--hcatalog-database dw \
--hcatalog-table ods_pre_T_JSZX_TF_KJ2_LL \
--hcatalog-storage-stanza 'stored as orc' \
--num-mappers 8

--query 参数的查询语句在Oracle中查询得到共计24563660数据,而加载到hive表dw.ods_pre_T_JSZX_TF_KJ2_LL中只有3070458数据。

24563660/8=3070457.5

这种巧合,刚好是一个mapper的向上取整量。这肯定有问题的,查看对应application的containers发现其实执行过程中是有做了split的:

例如mapper7,范围为:

复制代码
ROWNUM >= 15352287.875 AND ROWNUM < 18422745.250

这是mapper8,范围为:

复制代码
ROWNUM >= 18422745.250 AND ROWNUM < 21493202.625

但问题出现在Executing query,我把container7的语句放在Oracle中去执行,是没有返回任何结果集的:

但是container1中的Executing query查询却有结果集返回

这几个container中执行的Executing query查询,唯一不同的是条件ROWNUM的范围

复制代码
AND ( ROWNUM >= 1 ) AND ( ROWNUM < 3070458.375 )

那么ROWNUM到底是什么?为什么AND ( ROWNUM >= 1 ) AND ( ROWNUM < 3070458.375 )有结果集返回,而ROWNUM >= 18422745.250 AND ROWNUM < 21493202.625却没有?

要明白其中的原因,必须要明白Oracle中的ROWNUM到底是什么?

先看一组Oracle查询:

Oracle 的 ROWNUM 是一个特殊的伪列,它按查询返回的顺序动态分配给结果集中的每一行。因此,ROWNUM 仅在行被提取时分配,而不是基于数据表中的实际行号。

  1. 第一部分查询:

    SELECT COUNT(*) FROM LZJHGX.T_JSZX_TF_KJ2_LL WHERE TO_CHAR(TJSJ , 'YYYY-MM-DD') < TO_CHAR(SYSDATE,'YYYY-MM-DD')

    • 这一部分返回符合 TJSJ 条件的所有记录数,结果为 24,563,660。这表明符合条件的记录总数就是这么多。
  2. 第二部分查询:

    SELECT COUNT(*) FROM LZJHGX.T_JSZX_TF_KJ2_LL WHERE TO_CHAR(TJSJ , 'YYYY-MM-DD') < TO_CHAR(SYSDATE,'YYYY-MM-DD') AND ( ROWNUM >= 1 ) AND ( ROWNUM < 3070458.375 )

    • 这里你试图获取 ROWNUM 在 1 和 3,070,458.375 范围内的行数。然而,ROWNUM 在分配时是严格递增的,它只能用于获取从头开始的连续行。也就是说,只要有 ROWNUM < 3,070,458.375 的限制,查询将返回符合条件的头 3,070,458 行。
    • 因此,这个查询实际上在返回总符合条件的前 3,070,458 行。
  3. 第三部分查询:

    SELECT COUNT(*) FROM LZJHGX.T_JSZX_TF_KJ2_LL WHERE TO_CHAR(TJSJ , 'YYYY-MM-DD') < TO_CHAR(SYSDATE,'YYYY-MM-DD') AND ( ROWNUM >= 18422745.250 ) AND ( ROWNUM < 21493202.625 )

    • 这里的问题是,由于 ROWNUM 的工作方式,ROWNUM 永远不会满足 >= 18422745.250 和 < 21493202.625 这样的区间查询。ROWNUM 是从 1 开始的递增序列 ,如果你直接使用 ROWNUM >= 某值 的条件,那么 Oracle 会从头重新生成行号,这种逻辑不支持从特定行号直接开始。因此,这个查询会返回 0 结果。

主要原因总结:

  • ROWNUM 是一个动态生成的递增伪列 ,只能用于从查询的第一行依次生成,不能用来表示实际的物理行号。
  • 当你用条件 ROWNUM >= 某值 时,Oracle 会从第一个满足 WHERE 条件的行开始计算,无法跳过之前的行。

解决办法:所以在数据量很大时需要多个mapper并发执行时**ROWNUM万万不能作为splitby字段,**否则会出现数据量缺少,只有一个mapper数据量的问题。

方法1(不推荐):在--query利用开窗函数排序,数据量大时,非常消耗资源

方法2(推荐):将ROWNUM嵌套进子查询中,作为查询结果集中的一个字段,修改后的sqoop脚本如下:

bash 复制代码
sqoop import -D mapred.job.queue.name=highway \
-D mapreduce.map.memory.mb=4096 \
-D mapreduce.map.java.opts=-Xmx3072m \
-D sqoop.export.records.per.statement=1000 \
--fetch-size 10000 \
--connect "jdbc:oracle:thin:@//localhost:61521/LZY2" \
--username LZSHARE \
--password '123456' \
--query "SELECT * FROM(
SELECT
ROWNUM as splitby_column
,ZBDM
,ZBMC
,TO_CHAR(TJSJ, 'YYYY') AS tjsj_year
,TO_CHAR(TJSJ, 'MM') AS tjsj_month
,TO_CHAR(TJSJ, 'DD') AS tjsj_day
,TO_CHAR(TJSJ, 'YYYY-MM-DD HH24:MI:SS') AS TJSJ
,TJPD
......
,JLDWMC
,TO_CHAR(INPUTTIME, 'YYYY-MM-DD HH24:MI:SS') AS INPUTTIME
,UUID
,TO_CHAR(INSERTTIME, 'YYYY-MM-DD HH24:MI:SS') AS INSERTTIME
FROM LZJHGX.T_JSZX_TF_KJ2_LL
WHERE TO_CHAR(TJSJ , 'YYYY-MM-DD') < TO_CHAR(SYSDATE,'YYYY-MM-DD')) a WHERE \$CONDITIONS" \
--split-by splitby_column \
--hcatalog-database dw \
--hcatalog-table ods_pre_T_JSZX_TF_KJ2_LL \
--hcatalog-storage-stanza 'stored as orc' \
--num-mappers 20
相关推荐
其实防守也摸鱼35 分钟前
SQL注入实验笔记
android·运维·数据库·安全·oracle·自动化
做运维的阿瑞1 小时前
一张用户表串懂 MySQL 的库、表、列、行、主键
数据库·sql·mysql·oracle
oradh2 小时前
Oracle SQL Tuning Advisor调优工具
数据库·sql·oracle
一条小小yu3 小时前
mysql的锁
数据库·mysql·oracle
2601_9521963617 小时前
计算机科学与技术专业应届生投商业分析岗,需要哪些额外能力?
数据库·oracle
TLA技术19 小时前
LogMiner vs 裸日志解析(六):想提速,只能“堆实例”,结果把源库拖垮
数据库·oracle·flink·dba·迁移学习
IT毕设梦工厂1 天前
计算机毕业设计选题推荐:基于大数据的供应链数据分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hive·hadoop·python·数据分析·spark·课程设计
IT毕设梦工厂1 天前
计算机毕业设计选题推荐:基于大数据的城市尾气排放数据可视化分析|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hive·信息可视化·spark·毕业设计·课程设计·大数据毕设项目
IT毕设梦工厂1 天前
计算机毕业设计选题推荐:基于大数据的房地产交易数据分析与可视化|毕业设计选题|计算机毕设|选题推荐|毕设指导|项目定制|源码|高质量项目
大数据·hive·hadoop·python·数据分析·spark·课程设计
小程序设计1 天前
本科毕设避坑|大数据 / 单片机物联网 / 网络工程 / PLC / 机械设计选题与落地心得
java·hive·hadoop·单片机