今天在將公司的oracle的數據抽取到hive當中,根據時間字段做增量插入,然后合並采用按照id唯一主鍵的方式進行合並操作。
下面的代碼是增量導入的操作shell腳本
#!/bin/bash datenow=$(date -d 'last day' -I) databases=("FRONTBANK") sqoop import \ --connect jdbc:oracle:thin:自己的數據庫ip:1521:zdxdb \ --username frontbank \ --password sdff23s \ --table FRONTBANK.INCREAT_TABLE \ --fields-terminated-by "\t" \ --incremental lastmodified \ #這個配置項是對導入的數據做插入和更新操作 --check-column MODIFY_TIME \ #這個配置項是按照數據表中的某個字段定位要讀取的數據的位置 --last-value ${datenow} \ #這個配置項是加載最后一個導入數據到現在這段時間新增的數據,然后進行導入操作 --merge-key ID \ #這個配置項是對導入進來的數據進行合並的操作,這里是采用唯一主鍵的方式對數據進行合並操作 --hive-drop-import-delims \ -m 1 \ --target-dir /user/gxg/increment
在導入數據的過程中遇到的問題如下:
第一次在shell腳本當中執行的時候,出現了下面的問題
ERROR tool.ImportTool: Import failed: java.io.IOException: Could not load jar /tmp/sqoop-root/compile/42f2af520ed13e2dc948a98222d69466/FRONTBANK.INCREAT_TABLE.jar into JVM. (Could not find class FRONTBANK.INCREAT_TABLE.)
at org.apache.sqoop.util.ClassLoaderStack.addJarFile(ClassLoaderStack.java:92)
at com.cloudera.sqoop.util.ClassLoaderStack.addJarFile(ClassLoaderStack.java:36)
at org.apache.sqoop.tool.ImportTool.loadJars(ImportTool.java:120)
at org.apache.sqoop.tool.ImportTool.lastModifiedMerge(ImportTool.java:456)
at org.apache.sqoop.tool.ImportTool.importTable(ImportTool.java:522)
at org.apache.sqoop.tool.ImportTool.run(ImportTool.java:621)
at org.apache.sqoop.Sqoop.run(Sqoop.java:147)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:183)
at org.apache.sqoop.Sqoop.runTool(Sqoop.java:234)
at org.apache.sqoop.Sqoop.runTool(Sqoop.java:243)
at org.apache.sqoop.Sqoop.main(Sqoop.java:252)
Caused by: java.lang.ClassNotFoundException: FRONTBANK.INCREAT_TABLE
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:789)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at org.apache.sqoop.util.ClassLoaderStack.addJarFile(ClassLoaderStack.java:88)
這里顯示在merger的時候找不到類,而且沒這個jar包,但是在啟動日志中明明有加載這個包和這個類的操作。然后找資料說采用codegen的方式。但是各種報錯。
然后在想是不是數據包不共享造成的,於是我將腳本部署在oozie的工作流調度當中。居然可以可以運行,這個問題的原因應該是上傳的包在本地,然而其他的機器加載不到這個包所以類不存在了。
說到這里多提一句,在我們提交sqooop腳本的時候,會在本地產生一個jar包
當我們在集群上執行sqoop腳本的的時候,相當於數據目錄共享。所以不存在數據加載不到的問題。
第二個問題:
2019-01-08 17:03:35,929 INFO [IPC Server handler 2 on 37215] org.apache.hadoop.mapred.TaskAttemptListenerImpl: Diagnostics report from attempt_1546053074766_0184_m_000001_0:
Error: java.io.IOException: Cannot join values on null key. Did you specify a key column that exists? at org.apache.sqoop.mapreduce.MergeMapperBase.processRecord(MergeMapperBase.java:79) at org.apache.sqoop.mapreduce.MergeTextMapper.map(MergeTextMapper.java:58) at org.apache.sqoop.mapreduce.MergeTextMapper.map(MergeTextMapper.java:34) at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:145) at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:793) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341) at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1917) at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
出現這個問題的主要原因有兩點
(1)你設置合並的字段不是主鍵的形式,一定要設置成為主鍵
(2)第二點注意大小寫的問題。我的問題就是我的主鍵的字段是大寫的ID,我寫成了這樣 --merge-key id \
下面總結一下對於sqoop增量導入的總結:
在整個的sqooop導入操作中需要注意兩個東西,第一個就是我們的需要准備一個更新的字段(時間日期字段),第二個就是合並的字段負責更新數據的更新操作。其他的應該就沒有問題了
這里補充一點,我們只能定義數據目錄,不能直接將數據導入到hive當中否則會報下面的錯:
--incremental lastmodified option for hive imports is not supported. Please remove the parameter --incremental lastmodified.
這里需要補充另外一點,在我們增量導入的時候是分兩步走的
(1)將新增的數據導入進來 (這里可以指定導入的map數,也就是指定的並行讀)
(2)合並新導入的數據和之前的數據,這個過程有一點需要注意,我們在第一次全量導入數據的時候,指定的map數也就是最終形成的文件數。在合並的時候,他啟動的map的數量是文件數目的n+1個