Google bigquery 为什么我的PCollection(SCollection)大小与BigQuery表输入大小相比如此之大?

Google bigquery 为什么我的PCollection(SCollection)大小与BigQuery表输入大小相比如此之大?,google-bigquery,google-cloud-dataflow,apache-beam,spotify-scio,Google Bigquery,Google Cloud Dataflow,Apache Beam,Spotify Scio,上图是一个大查询表的表模式,它是在spotify的scio上运行的apache beam数据流作业的输入。如果您不熟悉scio,那么它是围绕Apache Beam Java SDK的Scala包装器。特别是,“scocollection包装PCollection”。我在BigQuery磁盘上的输入表是136 GB,但在数据流UI中查看我的SCOCollection的大小时,它是504.91 GB。 我知道BigQuery在数据压缩和表示方面可能要好得多,但大小增加了3倍以上似乎相当高。非常清楚

上图是一个大查询表的表模式,它是在spotify的scio上运行的apache beam数据流作业的输入。如果您不熟悉scio,那么它是围绕Apache Beam Java SDK的Scala包装器。特别是,“scocollection包装PCollection”。我在BigQuery磁盘上的输入表是136 GB,但在数据流UI中查看我的SCOCollection的大小时,它是504.91 GB。


我知道BigQuery在数据压缩和表示方面可能要好得多,但大小增加了3倍以上似乎相当高。非常清楚,我使用的是类型安全的大查询案例类(让我们称之为Clazz)表示,因此我的scolection是scolection[Clazz]类型,而不是scolection[TableRow]。TableRow是JavaJDK中的本机表示形式。关于如何减少内存分配有什么建议吗?它与输入中的特定列类型有关:字节、字符串、记录、浮点等?

这可能是由于TableRow格式包含列的字符串名称,从而增加了大小

考虑创建对象的PCollection,而不是TableRows。这允许您直接读入与模式匹配的对象,这将稍微减少数据大小

  /**
   * Reads from a BigQuery table or query and returns a {@link PCollection} with one element per
   * each row of the table or query result, parsed from the BigQuery AVRO format using the specified
   * function.
   *
   * <p>Each {@link SchemaAndRecord} contains a BigQuery {@link TableSchema} and a
   * {@link GenericRecord} representing the row, indexed by column name. Here is a
   * sample parse function that parses click events from a table.
   *
   * <pre>{@code
   * class ClickEvent { long userId; String url; ... }
   *
   * p.apply(BigQueryIO.read(new SerializableFunction<SchemaAndRecord, ClickEvent>() {
   *   public ClickEvent apply(SchemaAndRecord record) {
   *     GenericRecord r = record.getRecord();
   *     return new ClickEvent((Long) r.get("userId"), (String) r.get("url"));
   *   }
   * }).from("...");
   * }</pre>
   */
  public static <T> TypedRead<T> read(
      SerializableFunction<SchemaAndRecord, T> parseFn) {
/**
*从BigQuery表或查询中读取,并返回一个{@link PCollection},每个{@link PCollection}包含一个元素
*表或查询结果的每一行,使用指定的
*功能。
*
*每个{@link SchemaAndRecord}包含一个BigQuery{@link TableSchema}和一个
*{@link genericord}表示按列名索引的行。这是一个
*解析表中单击事件的示例解析函数。
*
*{@code
*类ClickEvent{long userId;字符串url;…}
*
*p.apply(BigQueryIO.read)(新的SerializableFunction(){
*公共ClickEvent应用(SchemaAndRecord记录){
*GenericRecord r=record.getRecord();
*返回新的ClickEvent((Long)r.get(“userId”),(String)r.get(“url”);
*   }
*})从(“…”)开始;
* }
*/
公共静态类型读取(
SerializableFunction(解析函数){

这可能是由于TableRow格式包含列的字符串名称,增加了大小

考虑创建一个对象的PCollection,而不是TableRows。这允许您直接读入与架构匹配的对象,这将稍微减少数据大小

  /**
   * Reads from a BigQuery table or query and returns a {@link PCollection} with one element per
   * each row of the table or query result, parsed from the BigQuery AVRO format using the specified
   * function.
   *
   * <p>Each {@link SchemaAndRecord} contains a BigQuery {@link TableSchema} and a
   * {@link GenericRecord} representing the row, indexed by column name. Here is a
   * sample parse function that parses click events from a table.
   *
   * <pre>{@code
   * class ClickEvent { long userId; String url; ... }
   *
   * p.apply(BigQueryIO.read(new SerializableFunction<SchemaAndRecord, ClickEvent>() {
   *   public ClickEvent apply(SchemaAndRecord record) {
   *     GenericRecord r = record.getRecord();
   *     return new ClickEvent((Long) r.get("userId"), (String) r.get("url"));
   *   }
   * }).from("...");
   * }</pre>
   */
  public static <T> TypedRead<T> read(
      SerializableFunction<SchemaAndRecord, T> parseFn) {
/**
*从BigQuery表或查询中读取,并返回一个{@link PCollection},每个{@link PCollection}包含一个元素
*表或查询结果的每一行,使用指定的
*功能。
*
*每个{@link SchemaAndRecord}包含一个BigQuery{@link TableSchema}和一个
*{@link genericord}表示按列名索引的行
*解析表中单击事件的示例解析函数。
*
*{@code
*类ClickEvent{long userId;字符串url;…}
*
*p.apply(BigQueryIO.read)(新的SerializableFunction(){
*公共ClickEvent应用(SchemaAndRecord记录){
*GenericRecord r=record.getRecord();
*返回新的ClickEvent((Long)r.get(“userId”),(String)r.get(“url”);
*   }
*})从(“…”)开始;
* }
*/
公共静态类型读取(
SerializableFunction(解析函数){

使用Kryo进行Case类序列化并不是最有效的,因为Kryo序列化了每个对象的完整类名。您可以通过注册经过扩展洗牌的类来解决这个问题

这将在Scio 0.7.x中用新的基于Magnolia宏的编码器推导解决


使用Kryo进行Case类序列化并不是最有效的,因为Kryo序列化了每个对象的完整类名。您可以通过注册经过扩展混洗的类来解决这个问题

这将在Scio 0.7.x中用新的基于Magnolia宏的编码器推导解决


我使用的是类型安全的大查询案例类,它可能只是scio对类型化读取的包装,而不是TableRow内部,Dataflow使用特定的编码器,并尝试对PCCollection的采样元素进行编码,以识别估计的大小。是否该编码器产生的输出可能远远大于行的实际大小?我使用的是类型安全的大查询案例类可能只是scio对类型化读取的包装,而不是TableRowDataflow内部,Dataflow使用某个编码器并尝试对PCollection的采样元素进行编码,以识别估计的大小。该编码器是否可能产生远大于实际行大小的输出?