在从Dataflow

时间:2016-02-03 14:41:22

标签: google-bigquery google-cloud-dataflow

根据 How do we set maximum_bad_records when loading a Bigquery table from dataflow?当从Dataflow将数据加载到BigQuery时,目前无法设置maxBadRecords配置。建议在将数据插入BigQuery之前验证数据流作业中的行。

如果我有TableSchemaTableRow,我该如何确保该行可以安全地插入到表中?

必须有一种更简单的方法来做到这一点,而不是遍历模式中的字段,查看它们的类型并查看行中值的类,对吧?这似乎容易出错,并且该方法必须是万无一失的,因为如果无法加载单行,整个管道就会失败。

更新

我的用例是一个ETL作业,最初将在JSON上运行(每行一个对象)登录云存储并批量写入BigQuery,但稍后将从PubSub读取对象并连续写入BigQuery。这些对象包含许多在BigQuery中不必要的信息,还包含甚至无法在模式中描述的部分(基本上是自由形式的JSON有效负载)。像时间戳这样的东西也需要格式化以与BigQuery一起使用。这个作业会有一些变种在不同的输入上运行并写入不同的表。

理论上它并不是一个非常困难的过程,它需要一个对象,提取一些属性(50-100),格式化其中一些并将对象输出到BigQuery。我或多或少只是循环遍历属性名称列表,从源对象中提取值,查看配置以查看属性是否应该以某种方式格式化,如果需要应用格式化(这可能是下行,划分毫秒时间戳) 1000,从URL中提取主机名等),并将值写入TableRow对象。

我的问题是数据混乱。有几亿个物体有一些不像预期的那样看起来很罕见,但是这些物品仍然很少见。有时,应包含字符串的属性包含整数,反之亦然。有时会有一个数组或一个应该有字符串的对象。

理想情况下,我想接受TableRow并将其传递给TableSchema并询问"这是否有效?"。

因为我不可能做的事情是我查看TableSchema对象并尝试自己验证/转换值。如果TableSchema表示某个属性属于STRING类型,则会在将其添加到value.toString()之前运行TableRow。如果它是INTEGER,我会检查它是IntegerLong还是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,因此无需担心由于单个错误输入而导致整个管道停止,因此无法完成此工作。人们如何做到这一点?

1 个答案:

答案 0 :(得分:8)

我假设您将文件中的JSON反序列化为Map<String, Object>。然后你应该能够用TableSchema递归地检查它。

我建议使用迭代方法开发模式验证,并执行以下两个步骤。

  1. 编写一个{J}行转换为PTransform<Map<String, Object>, TableRow>对象的TableRowTableSchema也应该是函数的构造函数参数。你可以开始使这个函数非常严格 - 要求JSON直接解析输入为Integer,例如,当找到BigQuery INTEGER模式时 - 并积极地声明错误记录。基本上,确保在处理时超级严格不会输出无效记录。

    我们的code here做了一些类似的事情 - 给定一个由BigQuery生成并作为JSON写入GCS的文件,我们递归地遍历模式并进行一些类型的转换。但是,我们不需要验证,因为BigQuery本身编写了数据。

    请注意,TableSchema对象不是Serializable。我们通过将TableSchemaDoFn构造函数中的PTransform转换为JSON String并返回来解决了问题。请参阅the code in BigQueryIO.java that uses the jsonTableSchema variable

  2. 使用&#34;死信&#34;此blog post中描述的策略用于处理错误记录 - 从PTransform输出有问题的Map<String, Object>行并将其写入文件。这样,您可以检查稍后验证失败的行。

  3. 您可以从一些小文件开始,然后使用DirectPipelineRunner而不是DataflowPipelineRunner。直接运行程序在您的计算机上运行管道,而不是在Google Cloud Dataflow服务上运行,它使用BigQuery流式写入。我相信当这些写入失败时,您将获得更好的错误消息。

    (我们对批处理作业使用GCS-&gt; BigQuery加载作业模式,因为它效率更高,成本效益更高,但BigQuery流在Streaming作业中写入,因为它们的延迟很低。)

    最后,就记录信息而言:

    • 绝对检查Cloud Logging(按照日志面板上的Worker Logs链接。
    • 如果您运行bq command-line utilitybq show -j PROJECT:dataflow_job_XXXXXXX,您可能会获得有关批量数据流触发的加载作业失败原因的更好信息。