Sqoop 导入按列数据类型拆分
Sqoop Import Split by Column Data type
sqoop import中Split by column的数据类型是否应该始终是数字数据类型(integer、bignint、numeric)?不能是字符串吗?
不,它必须是数字,因为根据规范:"By default , sqoop will use query select min(), max() from to find out boundaries for creating splits."替代方法是使用 --boundary-query,它也需要数字列。否则,Sqoop 作业将失败。如果您的 table 中没有这样的列,唯一的解决方法是仅使用 1 个映射器:“-m 1”。
是的,您可以拆分任何非数字数据类型。
但不推荐这样做
为什么?
对于拆分数据,Sqoop 触发
SELECT MIN(col1), MAX(col2) FROM TABLE
然后根据您的映射器数量进行分配。
现在以整数为例--split-by
列
Table 有一些 id
列的值为 1 到 100,并且您使用了 4 个映射器(-m 4
在您的 sqoop 命令中)
Sqoop 使用以下方法获取最小值和最大值:
SELECT MIN(id), MAX(id) FROM TABLE
输出:
1,100
按整数拆分很容易。您将制作 4 个部分:
- 1-25
- 25-50
- 51-75
- 76-100
现在字符串为 --split-by
列
Table 有一些 name
列的值为 "dev" 到 "sam" 并且您使用了 4 个映射器(-m 4
在您的 sqoop 命令中)
Sqoop 使用以下方法获取最小值和最大值:
SELECT MIN(id), MAX(id) FROM TABLE
输出:
开发人员,山姆
现在怎么分成4个部分。根据 sqoop docs,
/**
* This method needs to determine the splits between two user-provided
* strings. In the case where the user's strings are 'A' and 'Z', this is
* not hard; we could create two splits from ['A', 'M') and ['M', 'Z'], 26
* splits for strings beginning with each letter, etc.
*
* If a user has provided us with the strings "Ham" and "Haze", however, we
* need to create splits that differ in the third letter.
*
* The algorithm used is as follows:
* Since there are 2**16 unicode characters, we interpret characters as
* digits in base 65536. Given a string 's' containing characters s_0, s_1
* .. s_n, we interpret the string as the number: 0.s_0 s_1 s_2.. s_n in
* base 65536. Having mapped the low and high strings into floating-point
* values, we then use the BigDecimalSplitter to establish the even split
* points, then map the resulting floating point values back into strings.
*/
你会在代码中看到警告:
LOG.warn("Generating splits for a textual index column.");
LOG.warn("If your database sorts in a case-insensitive order, "
+ "this may result in a partial import or duplicate records.");
LOG.warn("You are strongly encouraged to choose an integral split column.");
在 Integer 示例的情况下,所有映射器将获得平衡负载(所有映射器将从 RDBMS 中获取 25 条记录)。
在字符串的情况下,数据排序的可能性较小。因此,很难为所有映射器提供相似的负载。
简而言之,将整数列作为 --split-by
列。
是的,我们可以,但由于性能问题,不推荐。因为我们知道 SQOOP 运行s 边界查询 "select min(pk/split-by column), max(pk/split-by column) from table where condition " 来计算映射器的拆分大小。
split-size = (max - min)/映射器数量
假设有 table 名员工。
id name age
1 baba 20
2 kishor 30
3 jay 40
..........
10001 pk 60
场景 1:
对 id 列执行拆分
在这种情况下,SQOOP 将触发员工的边界查询 select min(id),max(id) 以计算拆分大小。
min = 1
max = 100001
default no of mapper = 4
split-size = (10001-1)/4 = 25000
so each mapper will process 25000 lines of record.
mapper 1: 1 - 25000
mapper 2: 25001-50000
mapper 3: 50001-75000
mapper 4: 75001-100000
所以如果我们有完整的列,SQOOP 很容易分割记录。
场景 2:
对名称列执行拆分
在这种情况下,SQOOP 将触发“select min(name),max(name) from employee”来计算拆分大小。
min = baba, max= pk
SQOOP 无法轻松计算拆分大小,因为最小值和最大值具有文本值((最小值-最大值)/映射器的数量),因此它将 运行 TextSplitter class 执行拆分,这会产生额外的开销并可能影响性能。
注意:我们需要传递额外的参数 -D org.apache.sqoop.splitter.allow_text_splitter= true 才能使用 TextSplitter class.
sqoop import中Split by column的数据类型是否应该始终是数字数据类型(integer、bignint、numeric)?不能是字符串吗?
不,它必须是数字,因为根据规范:"By default , sqoop will use query select min(), max() from to find out boundaries for creating splits."替代方法是使用 --boundary-query,它也需要数字列。否则,Sqoop 作业将失败。如果您的 table 中没有这样的列,唯一的解决方法是仅使用 1 个映射器:“-m 1”。
是的,您可以拆分任何非数字数据类型。
但不推荐这样做
为什么?
对于拆分数据,Sqoop 触发
SELECT MIN(col1), MAX(col2) FROM TABLE
然后根据您的映射器数量进行分配。
现在以整数为例--split-by
列
Table 有一些 id
列的值为 1 到 100,并且您使用了 4 个映射器(-m 4
在您的 sqoop 命令中)
Sqoop 使用以下方法获取最小值和最大值:
SELECT MIN(id), MAX(id) FROM TABLE
输出:
1,100
按整数拆分很容易。您将制作 4 个部分:
- 1-25
- 25-50
- 51-75
- 76-100
现在字符串为 --split-by
列
Table 有一些 name
列的值为 "dev" 到 "sam" 并且您使用了 4 个映射器(-m 4
在您的 sqoop 命令中)
Sqoop 使用以下方法获取最小值和最大值:
SELECT MIN(id), MAX(id) FROM TABLE
输出:
开发人员,山姆
现在怎么分成4个部分。根据 sqoop docs,
/**
* This method needs to determine the splits between two user-provided
* strings. In the case where the user's strings are 'A' and 'Z', this is
* not hard; we could create two splits from ['A', 'M') and ['M', 'Z'], 26
* splits for strings beginning with each letter, etc.
*
* If a user has provided us with the strings "Ham" and "Haze", however, we
* need to create splits that differ in the third letter.
*
* The algorithm used is as follows:
* Since there are 2**16 unicode characters, we interpret characters as
* digits in base 65536. Given a string 's' containing characters s_0, s_1
* .. s_n, we interpret the string as the number: 0.s_0 s_1 s_2.. s_n in
* base 65536. Having mapped the low and high strings into floating-point
* values, we then use the BigDecimalSplitter to establish the even split
* points, then map the resulting floating point values back into strings.
*/
你会在代码中看到警告:
LOG.warn("Generating splits for a textual index column.");
LOG.warn("If your database sorts in a case-insensitive order, "
+ "this may result in a partial import or duplicate records.");
LOG.warn("You are strongly encouraged to choose an integral split column.");
在 Integer 示例的情况下,所有映射器将获得平衡负载(所有映射器将从 RDBMS 中获取 25 条记录)。
在字符串的情况下,数据排序的可能性较小。因此,很难为所有映射器提供相似的负载。
简而言之,将整数列作为 --split-by
列。
是的,我们可以,但由于性能问题,不推荐。因为我们知道 SQOOP 运行s 边界查询 "select min(pk/split-by column), max(pk/split-by column) from table where condition " 来计算映射器的拆分大小。 split-size = (max - min)/映射器数量
假设有 table 名员工。
id name age
1 baba 20
2 kishor 30
3 jay 40
..........
10001 pk 60
场景 1:
对 id 列执行拆分
在这种情况下,SQOOP 将触发员工的边界查询 select min(id),max(id) 以计算拆分大小。
min = 1
max = 100001
default no of mapper = 4
split-size = (10001-1)/4 = 25000
so each mapper will process 25000 lines of record.
mapper 1: 1 - 25000
mapper 2: 25001-50000
mapper 3: 50001-75000
mapper 4: 75001-100000
所以如果我们有完整的列,SQOOP 很容易分割记录。
场景 2:
对名称列执行拆分
在这种情况下,SQOOP 将触发“select min(name),max(name) from employee”来计算拆分大小。
min = baba, max= pk
SQOOP 无法轻松计算拆分大小,因为最小值和最大值具有文本值((最小值-最大值)/映射器的数量),因此它将 运行 TextSplitter class 执行拆分,这会产生额外的开销并可能影响性能。
注意:我们需要传递额外的参数 -D org.apache.sqoop.splitter.allow_text_splitter= true 才能使用 TextSplitter class.