使用 Sqoop 导入时 Parquet 文件中的脏值

Dirty values in Parquet files when importing with Sqoop

我正在使用 Sqoop1(版本 1.4.6,CDH 5.7.4)从 Oracle 导入。
Sqoop 创建一个临时的 Parquet Hive Table,然后我使用 Hive(直线)到达 insert into 目的地 table。
这种双步摄取是由于目标 table 具有与 Sqoop 的不同的列类型映射,因此使用 insert into 我可以即时转换它们。我也在 Snappy 中即时压缩。这工作正常。目前,我没有控制 Sqoop 导入命令的类型映射。在我的特殊情况下太复杂了。

一开始我是在平面文件中导入的,但是我有一些字段包含一堆字符,这些字符会破坏我的行,例如换行符、回车符 returns、制表符等等。出于这个和其他原因,我决定转向 Parquet(不幸的是,avro 不是一个选项,因为我们使用的工具不支持它)。
在我看来,像 Parquet 这样的二进制格式在处理这些字符时不会有问题。

原来我错了
select * from table 显示了一些损坏的行,经过大量调试后,我发现某些字段分为两部分。我能够看到一条被截断的记录(根据 Oracle 来源),其中一部分位于另一行(单独)。 由于我在 Sqoop 中使用自由格式查询,解决方案是在提取时使用替换函数 REPLACE(REPLACE(REPLACE(note, chr(10), ' '), chr(13), ' '), chr(09), ' ') AS NOTE 替换字符。

当然这显然是错误的方法,因为可能有其他字段带有脏字符,也可能有其他脏字符。

所以问题是:

  1. 我是不是认为 Parquet(或 avro,或其他二进制格式) 不关心字段中的字符?
  2. 我是不是做错了什么?
  3. 如何防止此类问题?

谢谢

答案:

  1. 你错了。 Parquet 不受换行符或制表符等内部定界符的影响。
  2. 没有。事实上,您的数据存储在 parquet 文件中,就像在 oracle 中一样。然而;当您将数据打印到屏幕上时,根据您的客户端(假设您使用配置单元客户端),您会看到结果损坏,因为服务器很可能以明文形式将数据发送到客户端。
  3. 为防止这种情况,在打印数据时,可以使用配置单元的函数:regexp_replace(your_text_column, "\t|\n|\r\n", " ")。这将防止您的客户的“混淆”。

此外,对于包含此类特定字符的数据,您不必使用 parquet。我认为配置单元的默认分隔符 (\001) 就足够了。该非打印字符不太可能出现在文本字段中。