【问题标题】:Oracle ROWID for Sqoop Split-By ColumnSqoop 拆分列的 Oracle ROWID
【发布时间】:2017-01-12 15:39:46
【问题描述】:

我有一个巨大的 oracle 表(事务),我的 oracle 表中的数据在“客户 ID”列上存在倾斜数据,因此少数映射器需要数小时才能完成工作,而其他映射器则在分钟。我看不到任何其他选项来避免数据倾斜,因为这是唯一可以拆分的列。我们可以结合其他列,如客户 ID、批次 ID、SEQ NUM 来进行多列拆分,但我知道 sqoop 不支持多列拆分。

我的目标是提取特定时期的交易数据(即一个月数据的唯一批次日期)。

我在 sqoop 中使用 10 个映射器尝试了以下选项。

--split-by "my column name"           //for example customer id
--where "my query condition"         //for example batch date

现在我正在考虑使用 ROWID,它可能会在映射器之间平均拆分行。我想过使用边界查询来获取 MIN & MAX ROW ID。下面是我要使用的 Sqoop 命令。

sqoop import \
--table Transaction \
--split-by ROWID \
--where "BATCH_DT=TO_DATE('03/31/2016','MM/DD/YYYY')" \
--boundary-query "SELECT MIN(ROWID) AS MIN, MAX(ROWID) AS MAXL FROM Transaction WHERE BATCH_DT=TO_DATE('03/31/2016','MM/DD/YYYY') GROUP BY CUSTOMERID, BATCHNO,BATCHSEQNO " \
--num-mappers 10 \
--target-dir /user/trans

需要建议这是正确的选择还是有其他方法。

我也想知道我们是否可以使用多重拆分列名。

【问题讨论】:

    标签: sqoop


    【解决方案1】:

    提供--boundary-query 只会节省您评估最小值和最大值的时间。所有映射器都将具有相同的范围查询。

    在您的情况下,sqoop 将生成边界查询,例如 -

    SELECT MIN(ROWID), MAX(ROWID) FROM (Select * From Transaction WHERE BATCH_DT=TO_DATE('03/31/2016','MM/DD/YYYY') ) t1

    您可以在 JDBC 客户端上尝试此查询和自定义边界查询,以检查哪个更快并使用那个。

    现在地图加载不均匀。

    是的,你是对的。目前,sqoop 不支持多列拆分。你必须选择一列。如果ROWID 分布均匀(我假设是),你应该使用它。

    所以,您的查询看起来不错。只需检查 compare--boundary-query


    编辑

    ROWID 类型的 Oracle 没有正确的 java 类型问题。

    在您的导入命令中添加--map-column-java ROWID=String 以将其映射到Java 的字符串。

    【讨论】:

    • 谢谢,我按照建议尝试了边界查询。现在我遇到了 2 个问题。一是警告消息“拆分可能无法分区”。另一个是终止 sqoop 作业的错误。错误是“Sqoop 没有给定 SQL 数据类型的拆分器。请使用不同的拆分列(参数 --split-by)或将映射器的数量降低到 1。未知的 SQL 数据类型:-8”跨度>
    • @Yoga 首先,你不需要手动写--boundary-query "SELECT MIN(ROWID), MAX(ROWID) FROM (Select * From Transaction WHERE BATCH_DT=TO_DATE('03/31/2016','MM/DD/YYYY') ) t1"。这是当您不使用--boundary-query 时,sqoop 将在内部生成的内容。在您的 sqoop 命令末尾添加--verbose 以查看扩展日志。您将在这些日志中找到此命令。我没有说这个查询比你的自定义边界查询快。我只是想让你比较这些并使用更好的......:)
    • @devツ 当我尝试这个时,看起来 Sqoop 抱怨 ROWID 必须是表中的列之一?
    • @jkamei 抱歉回复晚了。你能分享一下确切的问题吗?您可以提出一个新问题。
    • @devツ 完全没问题。我们最终选择了不同的路线并在不同的列上拆分。我们看到的问题是“--map-column-java”似乎特别想要 Oracle 表中的列,因此它拒绝了 ROWID。我们也尝试使用 oraoop 但这会降低性能。一旦我们必须解决这个问题,我会继续创建一个新问题:) 无论如何谢谢!
    【解决方案2】:

    您是否有关于 SEQ NUM 的索引,如果有,那么您可以在 --split-by 中使用 SEQ-NUM(我假设 SEQ-NUM 不会随机生成,它会以增量方式为每个事务填充)。所以你的 sqoop 命令可能看起来像这样

    sqoop import \ 
    --table Transaction \
    --split-by SEQ-NUM \
    --where "BATCH_DT=TO_DATE('03/31/2016','MM/DD/YYYY')" \ 
    --num-mappers 10 \
    --target-dir /user/trans
    

    【讨论】:

    • 不,该表具有批次日期和客户 ID 的索引。 SEQ_NUM 不是增量字段。对于一个批次日期,我们可能有多个客户,并且对于每个客户 ID,seq_num 将是递增的。所以 SEQ_NUM 将有一个批次日期的重复值。 Batch date、customer id 和 seq_num 的组合是唯一的。
    猜你喜欢
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 2023-01-27
    • 2021-10-20
    相关资源
    最近更新 更多