根据
How do we set maximum_bad_records when loading a Bigquery table from dataflow?当从Dataflow将数据加载到BigQuery时,目前无法设置maxBadRecords
配置。建议在将数据插入BigQuery之前验证数据流作业中的行。
如果我有TableSchema
和TableRow
,我该如何确保该行可以安全地插入到表中?
必须有一种更简单的方法来做到这一点,而不是遍历模式中的字段,查看它们的类型并查看行中值的类,对吧?这似乎容易出错,并且该方法必须是万无一失的,因为如果无法加载单行,整个管道就会失败。
更新
我的用例是一个ETL作业,最初将在JSON上运行(每行一个对象)登录云存储并批量写入BigQuery,但稍后将从PubSub读取对象并连续写入BigQuery。这些对象包含许多在BigQuery中不必要的信息,还包含甚至无法在模式中描述的部分(基本上是自由形式的JSON有效负载)。像时间戳这样的东西也需要格式化以与BigQuery一起使用。这个作业会有一些变种在不同的输入上运行并写入不同的表。
理论上它并不是一个非常困难的过程,它需要一个对象,提取一些属性(50-100),格式化其中一些并将对象输出到BigQuery。我或多或少只是循环遍历属性名称列表,从源对象中提取值,查看配置以查看属性是否应该以某种方式格式化,如果需要应用格式化(这可能是下行,划分毫秒时间戳) 1000,从URL中提取主机名等),并将值写入TableRow
对象。
我的问题是数据混乱。有几亿个物体有一些不像预期的那样看起来很罕见,但是这些物品仍然很少见。有时,应包含字符串的属性包含整数,反之亦然。有时会有一个数组或一个应该有字符串的对象。
理想情况下,我想接受TableRow
并将其传递给TableSchema
并询问"这是否有效?"。
因为我不可能做的事情是我查看TableSchema
对象并尝试自己验证/转换值。如果TableSchema
表示某个属性属于STRING
类型,则会在将其添加到value.toString()
之前运行TableRow
。如果它是INTEGER
,我会检查它是Integer
,Long
还是BigInteger
,依此类推。这种方法的问题在于我只是猜测BigQuery中有什么用。它将为FLOAT
接受哪些Java数据类型?对于TIMESTAMP
?我认为我的验证/演员表可以解决大多数问题,但总有例外和边缘情况。
根据我的经验,这是非常有限的,整个工作流程(工作?工作流程?不确定正确的术语)如果单行失败BigQuery的验证失败(就像常规加载那样除非{{ 1}}设置为足够大的数字)。它也失败了表面上有用的消息,如' BigQuery import job" dataflow_job_xxx"失败。原因:(5db0b2cdab1557e0):BigQuery工作" dataflow_job_xxx"在项目" xxx"完成错误:errorResult:为非记录字段指定的JSON映射,错误:为非记录字段指定的JSON映射,错误:为非记录字段指定的JSON映射,错误:为非记录字段指定的JSON映射,error:为非记录字段指定的JSON映射,错误:为非记录字段指定的JSON映射' 。也许在某个地方可以看到更详细的错误消息,可以告诉我它属于哪个属性以及价值是多少?如果没有这些信息,它就可以说出错误的数据"。
据我所知,至少在批处理模式下运行时,Dataflow会将maxBadRecords
对象写入云存储中的暂存区域,然后在所有内容完成后启动加载。这意味着我无处可捕获任何错误,我的代码在加载BigQuery时不再运行。我还没有以流媒体方式开展任何工作,但我不确定那里会有什么不同,从我(理所当然有限的)理解基本原理是相同的,它只是批量大小更小。
人们使用Dataflow和BigQuery,因此无需担心由于单个错误输入而导致整个管道停止,因此无法完成此工作。人们如何做到这一点?
答案 0 :(得分:8)
我假设您将文件中的JSON反序列化为Map<String, Object>
。然后你应该能够用TableSchema
递归地检查它。
我建议使用迭代方法开发模式验证,并执行以下两个步骤。
编写一个{J}行转换为PTransform<Map<String, Object>, TableRow>
对象的TableRow
。 TableSchema
也应该是函数的构造函数参数。你可以开始使这个函数非常严格 - 要求JSON直接解析输入为Integer,例如,当找到BigQuery INTEGER模式时 - 并积极地声明错误记录。基本上,确保在处理时超级严格不会输出无效记录。
我们的code here做了一些类似的事情 - 给定一个由BigQuery生成并作为JSON写入GCS的文件,我们递归地遍历模式并进行一些类型的转换。但是,我们不需要验证,因为BigQuery本身编写了数据。
请注意,TableSchema
对象不是Serializable
。我们通过将TableSchema
或DoFn
构造函数中的PTransform
转换为JSON String
并返回来解决了问题。请参阅the code in BigQueryIO.java
that uses the jsonTableSchema
variable。
使用&#34;死信&#34;此blog post中描述的策略用于处理错误记录 - 从PTransform输出有问题的Map<String, Object>
行并将其写入文件。这样,您可以检查稍后验证失败的行。
您可以从一些小文件开始,然后使用DirectPipelineRunner
而不是DataflowPipelineRunner
。直接运行程序在您的计算机上运行管道,而不是在Google Cloud Dataflow服务上运行,它使用BigQuery流式写入。我相信当这些写入失败时,您将获得更好的错误消息。
(我们对批处理作业使用GCS-&gt; BigQuery加载作业模式,因为它效率更高,成本效益更高,但BigQuery流在Streaming作业中写入,因为它们的延迟很低。)
最后,就记录信息而言:
Worker Logs
链接。bq
command-line utility:bq show -j PROJECT:dataflow_job_XXXXXXX
,您可能会获得有关批量数据流触发的加载作业失败原因的更好信息。