假设我在csv文件中包含以下数据:
'"tom","jones","hello,\nMy name is tom"\x01\n"sarah","smith","hello"\x01\n'
行终止符为\x01\n
。是否可以将其直接加载到GCS中(而无需先进行预格式化)?我的思考过程是:
\x00ff
)将其加载到CSV中,以将所有数据收集到一行。但是,当我们有连续的线路时,我们会遇到一个问题,因为BQ不“支持”(如果您要称呼它)行排序。这是我现在在BQ中的数据:
我们可以看到行顺序不起作用,因此,例如,使用UDF来获取所需的正确csv数据是不可能的。
这里还有其他可能的方法吗?只是为了澄清一下,我希望通过BigQuery转换GCS上已经存在的CSV文件,而不必将该文件下载到单独的服务器上进行处理,然后再加载到BQ中。
作为参考,这是我当前正在使用的代码:
# /tmp/schema_external_nonstandard_csv.json
{
"schema": {
"fields": [
{
"name": "data",
"type": "STRING"
}
]
},
"sourceFormat": "CSV",
"sourceUris": [
"gs://XY-bq/ns.csv"
],
"csvOptions": {
"fieldDelimiter": "\u00ff",
"quote": ""
},
"maxBadRecords": 1000000
}
$ bq mk --external_table_definition=/tmp/schema_external_nonstandard_csv.json datadocs-163219:bqtesting.ns
$ bq query --nouse_legacy_sql 'CREATE TABLE `XY-163219.bqtesting.ns1` AS select * from `XY-163219.bqtesting.ns`'
答案 0 :(得分:2)
我想到了一些纯粹的BigQuery解决方案:
“分隔符可以是任何ISO-8859-1单字节字符。”
REGEXP_REPLACE
最好的方法是单行内部有换行符:CREATE OR REPLACE TABLE test.separator_final AS
SELECT
REGEXP_REPLACE(data, r"\\x01\\n", "\n") AS data
FROM
test.separator_external
从上一点开始,可以使用“ hack”将行扩展为不同的行(请参见答案here)。但是,需要注意的是,您需要先验地了解拆分的数量,在这种情况下,不一致的数量。
您已经在使用的,但是添加了一个行号,以便可以将数据合并回去。这可能有用,但确保保留行顺序也会很复杂。
如果我们考虑将其他GCP产品用作GCS和BigQuery之间的中间人,我们可以找到其他有趣的解决方案:
使用Dataprep,它在后台运行Dataflow。有一个替换转换(docs),并且可以以编程方式生成和调用数据流模板。
使用数据流。我实际上使用此gist测试了该解决方案,它的工作原理是: 我认为可以通过创建模板(自定义分隔符可以是输入参数)很好地扩展该模板,并在每次使用Cloud Functions将文件上传到GCS时(NoOps解决方案)触发该模板。
简而言之,我们使用TextIO.read().from(file)
从文件中读取记录,其中file
是GCS路径(启动作业时提供input
和output
参数)。我们还可以使用withDelimiter()
来使用虚拟定界符来避免冲突(此处再次限制为单个字节,因此我们不能直接传递真实的定界符)。然后,对于每一行,我们用c.element().split("\\\\x01\\\\n")
除以实际的定界符。请注意,我们需要对已经转义的字符进行转义(您可以在JSON查询结果中以正常负载验证该字符),因此需要四倍的反斜杠。
p
.apply("GetMessages", TextIO.read().from(file))
.apply("ExtractRows", ParDo.of(new DoFn<String, String>() {
@ProcessElement
public void processElement(ProcessContext c) {
for (String line : c.element().split("\\\\x01\\\\n")) {
if (!line.isEmpty()) {
c.output(line);
}
}
}
}))
结果:
请记住,正如@hlagos指出的那样,由于BigQuery中的行数限制或分配给Dataflow中单个工作人员的不可拆分步骤,您可能会遇到很大的单行CSV问题。