我有一个AWS Glue Crawler,在S3上有3个数据存储,每个数据存储都是表的S3路径。当文件以分号分隔时,爬网程序运行良好,而当文件以制表符分隔时,它会崩溃。然而,根据AWS官方文件,CSV内置分类器
检查以下分隔符:逗号(,(、管道(|(、制表符(\t(、分号(;(和Ctrl-A(\u0001(。Ctrl-A是"起始标题"的Unicode控制字符。
让我提供更多详细信息。
S3的结构如下(都在同一个桶内(:
|--table_1
|---------|partion_a=1
|------------------|partion_b=2
|---------------------------|partion_c=3
|------------------------------------|partion_d=4
|-----------------------------------------------|file_1.csv
|--table_2
|---------|partion_a=1
|------------------|partion_b=2
|---------------------------|partion_c=3
|------------------------------------|partion_d=4
|-----------------------------------------------|file_2.csv
|--table_3
|---------|partion_a=1
|------------------|partion_b=2
|---------------------------|partion_c=3
|--------------------------------------|file_3a.csv
|---------------------------|partion_c=4
|--------------------------------------|file_3b.csv
|---------------------------|partion_c=5
|--------------------------------------|file_3c.csv
爬网程序按预期处理table_1和table_2,即创建2个表,将分类标识为csv,创建3个分区,检测标头。
虽然它不能正常工作于表3:
- 它确实在数据目录中创建了一个表
- 它确实添加了分区(所有分区,即partition_c=3、4和5(
- 但是它不会检测到架构,即根本没有列
CloudWathc日志中没有报告错误,而如果我在Athena上查询表_3(SELECT*FROM table_3 LIMIT 10(,我会得到以下错误:
"HIVE_UNKNOWN_ERROR: serDe should not be accessed from a null StorageFormat"
这些是表文件之间的主要区别:
- Table_1文件较小,约为20KB,并且以分号分隔
- Table_2文件大于Table_1,但仍然很小,即大约20MB,并且以分号分隔
- Table_3文件要大得多,即大约200 MB,并且是选项卡分隔的
我曾尝试将table_3文件重命名为.tsv并重新运行爬网程序,但没有任何更改。我还尝试过为table_3使用一个较小的文件,即只有partition_c=3,大小约为2MB,但没有任何变化。
你知道为什么会发生这种情况以及如何解决吗?我应该只为.tsv文件创建一个自定义分类器吗?
为了创建TSV表而不是(逗号(,(、管道(|(、制表符(\t(、分号(;(和Ctrl-a(\u0001((,您需要通过AWS Athena编辑器查询创建表和架构定义。
Athena中负责读取和解析数据的组件被称为serde,是序列化程序/反序列化程序的缩写。如果在创建Athena表时没有指定任何其他内容,则会得到一个名为LazySimpleSerDe的serde,它是为CSV等分隔文本创建的。它可以针对不同的分隔符、转义符和行尾等进行配置。
定义createtable命令并提供表模式后,需要添加以下内容:
...
ROW FORMAT DELIMITED
FIELDS TERMINATED BY 't'
ESCAPED BY '\'
LINES TERMINATED BY 'n'
...
在幕后,当您看到实际的表DML时,您将看到它是如何使用以下regex解析数据的:
ROW FORMAT SERDE
'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
'input.regex'='^(?!#)([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)\s+[^(]+[(]([^;]+).*\%20([^/]+)[/](.*)$')
阅读更多:
用于CSV、TSV和自定义分隔文件的LazySimpleSerDe
使用CSV