Google cloud storage 为什么在运行管道时零字节文件会写入GCS?

Google cloud storage 为什么在运行管道时零字节文件会写入GCS?,google-cloud-storage,google-cloud-dataflow,Google Cloud Storage,Google Cloud Dataflow,我们的工作/管道正在将ParDo转换的结果写回GCS,即使用TextIO.Write.to(“gs://…”) 我们注意到,当作业/管道完成时,它会在输出桶中留下大量0字节的文件 管道的输入来自GCS的多个文件,因此我假设结果是分片的,这很好 但是为什么我们会得到空文件呢 这些空碎片很可能是中间管道步骤的结果,该步骤变得有些稀疏,一些预分区的碎片中没有记录 例如,如果在TextIO.Write之前有一个GroupByKey,比如说,键空间被分为[00,01]、[01,02]、[fe,ff](总共

我们的工作/管道正在将ParDo转换的结果写回GCS,即使用
TextIO.Write.to(“gs://…”)

我们注意到,当作业/管道完成时,它会在输出桶中留下大量0字节的文件

管道的输入来自GCS的多个文件,因此我假设结果是分片的,这很好

但是为什么我们会得到空文件呢


这些空碎片很可能是中间管道步骤的结果,该步骤变得有些稀疏,一些预分区的碎片中没有记录

例如,如果在TextIO.Write之前有一个GroupByKey,比如说,键空间被分为[00,01]、[01,02]、[fe,ff](总共255个碎片),但是从这个GroupByKey的输入中发出的所有实际键都在[34,81]和[a3,b5]范围内,那么将生成255个输出文件,但大多数文件都是空的。(这是一个假设的分区方案,只是为了给您一个想法)

我的其余答案将以问答的形式给出

为什么要生成空文件?如果没有输出,就不要创建文件! 的确,从技术上讲,可以避免生成它们,例如,在写入第一个元素时,在写入输出时懒洋洋地打开它们。好吧,我们通常不会这样做,因为空输出文件通常不是问题,空文件比没有文件更容易理解:如果只有50个碎片中的第一个变成了非空的,并且您只有一个名为00001-of-000050的输出文件:您可能想知道其他49个碎片发生了什么

但是为什么不添加一个后处理步骤来删除空文件呢?原则上,如果空输出成为一个大问题,我们可以添加一个后处理步骤,删除空输出并重命名其余的输出(与xxxxx-of-YYYY文件模式一致)

空碎片的存在是否表明我的管道中存在问题? 大量空分片可能意味着系统选择的分片是次优/不均匀的,我们应该将计算分为更少、更均匀的分片。如果这对您来说是个问题,您能否提供有关管道输出的更多详细信息,例如:您的屏幕截图显示非空输出也非常小:它们是否只包含一个分片少量记录?(如果是,在不事先知道数据的情况下,可能很难实现统一的分片)

但是我的原始输入的分片不是空的,输出的分片不是镜像输入的分片吗?如果管道有GroupByKey(或派生的)操作时,输入和输出中的分片数会有不同的中间步骤:例如,一个操作可能消耗30个输入分片,但产生50个输出分片,反之亦然。在其他一些不涉及GroupByKey的情况下,输入和输出中的分片数也可能不同


TL;DR如果您的总体输出是正确的,那么这不是一个bug,但请告诉我们这是否是您的问题:)

您是否明确指定了碎片的数量?只是想知道,因为其他文件非常小(我认为数据流不能保证文件大小的平衡).Ahh,屏幕截图只显示了一些文件。下面还有更多,更大。回答很好,很全面。太棒了!空文件不是问题。我们只是担心它可能表明我们的管道有问题。不过我还有一个问题。假设我们有10个输入文件。我们处理了所有10个文件,但都是这样me实例其中一个文件中的所有记录都被我们的ParDo过滤掉(例如,无效记录)。这会导致一个空文件吗?这取决于您所做的处理类型。如果您的管道确实读取此输入,则过滤并写入输出,而无需额外设置(例如在输出上指定明确数量的碎片,AFAIK将强制重新碎片)然后是的,我认为这将导致1个空文件。如果在输入和输出之间进行分组等操作,则它们的碎片无关,并且哪个输入碎片为空与哪个输出碎片为空无关。