需要有关Sqoop增量进口的建议。
假设我在第1天有一个策略1的客户,我在第1天将这些记录导入HDFS,我在Part Files中看到它们。
在第2天,同一客户添加了策略2,在增量导入sqoop运行之后,我们是否只获得部分文件中的新记录?
在这种情况下,如何使用Sqoop获取旧的和增量的附加/最后修改记录?
答案 0 :(得分:21)
考虑一个包含3条记录的表,您已使用sqoop
将其导入hdfsSELECT REPLACE(col,'/','')
现在您在表格中有其他记录,但现有记录没有更新
+------+------------+----------+------+------------+
| sid | city | state | rank | rDate |
+------+------------+----------+------+------------+
| 101 | Chicago | Illinois | 1 | 2014-01-25 |
| 101 | Schaumburg | Illinois | 3 | 2014-01-25 |
| 101 | Columbus | Ohio | 7 | 2014-01-25 |
+------+------------+----------+------+------------+
sqoop import --connect jdbc:mysql://localhost:3306/ydb --table yloc --username root -P
在这里,您应该使用+------+------------+----------+------+------------+
| sid | city | state | rank | rDate |
+------+------------+----------+------+------------+
| 101 | Chicago | Illinois | 1 | 2014-01-25 |
| 101 | Schaumburg | Illinois | 3 | 2014-01-25 |
| 101 | Columbus | Ohio | 7 | 2014-01-25 |
| 103 | Charlotte | NC | 9 | 2013-04-22 |
| 103 | Greenville | SC | 9 | 2013-05-12 |
| 103 | Atlanta | GA | 11 | 2013-08-21 |
+------+------------+----------+------+------------+
和--incremental append
,它指定在确定要导入的行时要检查的列。
--check-column
上面的代码将根据最后一个值插入所有新行。
现在我们可以想到行中有更新的第二种情况
sqoop import --connect jdbc:mysql://localhost:3306/ydb --table yloc --username root -P --check-column rank --incremental append --last-value 7
这里我们使用增量lastmodified,我们将根据日期获取所有更新的行。
+------+------------+----------+------+------------+
| sid | city | state | rank | rDate |
+------+------------+----------+------+------------+
| 101 | Chicago | Illinois | 1 | 2015-01-01 |
| 101 | Schaumburg | Illinois | 3 | 2014-01-25 |
| 101 | Columbus | Ohio | 7 | 2014-01-25 |
| 103 | Charlotte | NC | 9 | 2013-04-22 |
| 103 | Greenville | SC | 9 | 2013-05-12 |
| 103 | Atlanta | GA | 11 | 2013-08-21 |
| 104 | Dallas | Texas | 4 | 2015-02-02 |
| 105 | Phoenix | Arzona | 17 | 2015-02-24 |
+------+------------+----------+------+------------+
答案 1 :(得分:3)
在回答第一个问题时,这取决于您如何运行import语句。如果您使用--incremental append
选项,则会指定--check-column
和--last-value
个参数。这些将准确地指示拉出哪些记录,它们将简单地附加到您的表格中。
例如:您可以为DATE
参数和非常早的日期指定--check-column
类型列(例如' 1900-01-01'或 Day1 在你的情况下)--last-value
这将继续将源表中的所有内容(创建重复的行)附加到目的地。在这种情况下,创建的新零件文件将包含新旧记录。您还可以使用增加的ID列并继续输入小ID,这将具有相同的效果。但是,如果--last-value
Day2 ,则会有其他部分文件包含仅新记录。我不确定你是否想知道你是否会丢失旧记录(以防万一),但事实并非如此。
last-modified
的{{1}}参数只有在将来返回并更新现有行的某些属性时才有用。在这种情况下,它会将表中的旧数据(并添加新内容)替换为源表中现在的行的更新版本。希望这有帮助!
哦,所有这些都是基于The Sqoop用户指南第7.2.7节https://sqoop.apache.org/docs/1.4.2/SqoopUserGuide.html#_incremental_imports
和Apache Sqoop Cookbook的第3章(该章实际上太棒了!)
答案 2 :(得分:1)
让我们在这里举例说明,您的客户表包含两列cust_id和策略,custid也是您的主键,您只想向前面插入数据100
方案1: - 根据cust_id字段附加新数据
阶段1: -
最近在我们想要在HDFS中导入的客户表中插入了3条记录
| custid | Policy |
| 101 | 1 |
| 102 | 2 |
| 103 | 3 |
这是
的sqoop命令sqoop import \
--connect jdbc:mysql://localhost:3306/db \
--username root -P \
--table customer \
--target-dir /user/hive/warehouse/<your db>/<table> \
--append \
--check-column custid \
--incremental append \
--last-value 100
阶段2: - 最近在客户表中插入了4条记录,我们要在HDFS中导入
| custid | Policy |
| 104 | 4 |
| 105 | 5 |
| 106 | 6 |
| 107 | 7 |
这是
的sqoop命令sqoop import \
--connect jdbc:mysql://localhost:3306/db \
--username root -P \
--table customer \
--target-dir /user/hive/warehouse/<your db>/<table> \
--append \
--check-column custid \
--incremental append \
--last-value 103
所以这四个属性我们将需要cosider来插入新记录
--append \
--check-column <primary key> \
--incremental append \
--last-value <Last Value of primary key which sqoop job has inserted in last run>
方案2: - 附加新数据+根据cust_id字段更新现有数据
以下1个新记录,其中已插入cust id 108,并且最近在我们要在HDFS中导入的customer表中更新了cust id 101和102
| custid | Policy |
| 108 | 8 |
| 101 | 11 |
| 102 | 12 |
sqoop import \
--connect jdbc:mysql://localhost:3306/db \
--username root -P \
--table customer \
--target-dir /user/hive/warehouse/<your db>/<table> \
--append \
--check-column custid \
--incremental lastmodified \
--last-value 107
所以这四个属性我们将在同一个命令中用于插入/更新记录的cosider
--append \
--check-column <primary key> \
--incremental lastmodified \
--last-value <Last Value of primary key which sqoop job has inserted in last run>
我特别提到主键,好像表没有主键,那么需要考虑的更多属性是: -
多个映射器默认执行sqoop作业,因此映射器需要根据某些键拆分数据,所以
要么我们必须专门定义-m 1选项来说只有一个映射器将执行此操作
或者我们必须指定任何其他键(通过使用sqoop属性--split-by),您可以唯一地标识数据然后可以使用
答案 3 :(得分:1)
步骤1:导入整个表。这将作为指定HDFS位置的part-m文件提供(例如/ user / abc / def / part-m-00000) 步骤2:仅导入增量记录。这将在另一个位置(例如/ user / abc / def1 / part-m-00000)
现在两个数据都可用,您可以使用sqoop merge选项根据键列合并两者。
请参阅以下文档。了解更多详情
https://sqoop.apache.org/docs/1.4.3/SqoopUserGuide.html#_literal_sqoop_merge_literal
答案 4 :(得分:0)
您还可以尝试自由格式查询,该查询将根据特定条件进行更改。您可以使用Sqoop Client编写Java代码来执行相同的操作: How to use Sqoop in Java Program?
答案 5 :(得分:0)
在这种用例中,总是寻找增量附加的真正增量字段。 并且对于最后修改的外观,最适合的字段是modified_date,或者同样是某些字段,用于自sqoop-ed以来已更改的字段。只有那些和那些行将被更新,在hdfs位置添加更新的行需要增量追加。
答案 6 :(得分:0)
这里已经有很好的回应。除了这些,您还可以尝试Sqoop查询方法。您可以根据条件自定义查询以检索更新的记录。
示例1:
$ sqoop导入\ -从(a.id == b.id)WHERE $ CONDITIONS的JOIN b中查询'SELECT a。,b。 --split-by a.id --target-dir / tmp / MyNewloc
示例2:
sqoop import --connect "jdbc:jtds:sqlserver://MYPD22:1333;databaseName=myDb" --target-dir /tmp/MyNewloc --fields-terminated-by \| --username xxx --password='xxx' --query "select * from Policy_Table where Policy_ID > 1 AND \$CONDITIONS" -m1
不要忘记在Where子句中提供$ CONDITIONS。
您可以使用2种方法执行此操作。
方法1 -Using Sqoop Merge
方法2 -将新生成的part-m文件复制到原始表目标目录中。 (将部分M文件从/ tmp / MyNewloc复制到/ tmp / MyOriginalLoc /)
1)现在使用“位置”作为原始表目标目录创建一个配置单元表,其中包含原始part-m文件和新记录part-m文件。
CREATE EXTERNAL TABLE IF NOT EXISTS Policy_Table(
Policy_ID string,
Customer_Name string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'
STORED AS TEXTFILE
LOCATION '/tmp/MyOriginalLoc/';