簡體   English   中英

從本地磁盤將數據加載到BigQuery和Google雲存儲的策略

[英]Strategy for loading data into BigQuery and Google cloud Storage from local disk

我在本地磁盤中有2年大小約為300GB的組合數據,這是我從teradata中提取的。 我必須將相同的數據加載到谷歌雲存儲和BigQuery表。

谷歌雲存儲中的最終數據應該以壓縮格式進行日間隔離(每天文件應該是gz格式的單個文件)。 我還必須在日常分區表中加載BigQuery中的數據,即每天的數據應存儲在一個分區中。

我首先將2年的組合數據加載到谷歌存儲。 然后嘗試使用谷歌數據流,通過使用數據流中的分區概念並將其加載到谷歌雲存儲(日常數據流分區與大查詢分區不同)來明智地隔離數據。 但是數據流不允許創建730個分區(2年),因為它達到413請求實體太大 (管道的序列化JSON表示的大小超過允許限制“)。

所以我運行了兩次數據流作業,每年過濾數據。 它過濾了每一年的數據並將其寫入谷歌雲存儲中的單獨文件中,但由於數據流當前無法寫入壓縮文件,因此無法壓縮它。

看到第一種方法失敗,我想到如上所述使用數據流中的分區來過濾1合並數據中的一年數據,並將其直接寫入BigQuery,然后以壓縮格式將其導出到谷歌存儲。 這個過程將重復兩次。 但是在這種方法中,我不能一次寫入超過45天的數據,因為我反復命中java.lang.OutOfMemoryError:Java堆空間問題 所以這個開始也失敗了

任何有助於制定日期明智的隔離遷移到壓縮格式的谷歌存儲和BigQuery的策略的幫助會有很大的幫助嗎?

目前,對結果進行分區是生成多個輸出文件/表的最佳方法。 您可能遇到的是每個寫入為上載分配緩沖區的事實,因此如果您有一個分區后跟N個寫入,則有N個緩沖區。

有兩種策略可以完成這項工作。

  1. 您可以減少使用上傳緩沖區的大小uploadBufferSizeBytes在選項GcsOptions 請注意,這可能會降低上傳速度,因為需要更頻繁地刷新緩沖區。
  2. 您可以在分區后對每個PCollection應用Reshuffle操作。 這將限制同時運行的並發BigQuery接收器的數量,因此將分配更少的緩沖區。

例如,您可以執行以下操作:

PCollection<Data> allData = ...;
PCollectionList<Data> partitions = allData.apply(Partition.of(...));

// Assuming the partitioning function has produced numDays partitions,
// and those can be mapped back to the day in some meaningful way:
for (int i = 0; i < numDays; i++) {
  String outputName = nameFor(i); // compute the output name
  partitions.get(i)
    .apply("Write_" + outputName, ReshuffleAndWrite(outputName));
}

這使用了這兩個輔助PTransforms:

private static class Reshuffle<T>
  extends PTransform<PCollection<T>, PCollection<T>> {
  @Override
  public PCollection<T> apply(PCollection<T> in) {
    return in
      .apply("Random Key", WithKeys.of(
          new SerializableFunction<T, Integer>() {
            @Override
            public Integer apply(Data value) {
              return ThreadLocalRandom.current().nextInt();
            }
          }))
      .apply("Shuffle", GroupByKey.<Integer, T>create())
      .apply("Remove Key", Values.create());
  }
}

private static class ReshuffleAndWrite 
  extends PTransform<PCollection<Data>, PDone> {

  private final String outputName;
  public ReshuffleAndWrite(String outputName) {
    this.outputName = outputName;
  }

  @Override
  public PDone apply(PCollection<Data> in) {
    return in
      .apply("Reshuffle", new Reshuffle<Data>())
      .apply("Write", BigQueryIO.Write.to(tableNameFor(outputName)
        .withSchema(schema)
        .withWriteDisposition(WriteDisposition.WRITE_TRUNCATE));
  }
}

讓我們看看這是否有幫助?

步驟+偽代碼

1 - 將組合數據(300GB)上傳到BigQuery到CombinedData表

2 - 拆分年份(費用1x2x300GB = 600GB)

SELECT * FROM CombinedData WHERE year = year1 -> write to DataY1 table  
SELECT * FROM CombinedData WHERE year = year2 -> write to DataY2 table  

3 - 拆分為6個月(費用2x2x150GB = 600GB)

SELECT * FROM DataY1 WHERE month in (1,2,3,4,5,6) -> write to DataY1H1 table
SELECT * FROM DataY1 WHERE month in (7,8,9,10,11,12) -> write to DataY1H2 table
SELECT * FROM DataY2 WHERE month in (1,2,3,4,5,6) -> write to DataY2H1 table
SELECT * FROM DataY2 WHERE month in (7,8,9,10,11,12) -> write to DataY2H2 table

4 - 拆分為3個月(費用4x2x75GB = 600GB)

SELECT * FROM DataY1H1 WHERE month in (1,2,3) -> write to DataY1Q1 table
SELECT * FROM DataY1H1 WHERE month in (4,5,6) -> write to DataY1Q2 table
SELECT * FROM DataY1H2 WHERE month in (7,8,9) -> write to DataY1Q3 table
SELECT * FROM DataY1H2 WHERE month in (10,11,12) -> write to DataY1Q4 table

SELECT * FROM DataY2H1 WHERE month in (1,2,3) -> write to DataY2Q1 table
SELECT * FROM DataY2H1 WHERE month in (4,5,6) -> write to DataY2Q2 table
SELECT * FROM DataY2H2 WHERE month in (7,8,9) -> write to DataY2Q3 table
SELECT * FROM DataY2H2 WHERE month in (10,11,12) -> write to DataY2Q4 table

5 - 每個季度拆分為1個月和2個月(成本8x2x37.5GB = 600GB)

SELECT * FROM DataY1Q1 WHERE month = 1 -> write to DataY1M01 table
SELECT * FROM DataY1Q1 WHERE month in (2,3) -> write to DataY1M02-03 table
SELECT * FROM DataY1Q2 WHERE month = 4 -> write to DataY1M04 table
SELECT * FROM DataY1Q2 WHERE month in (5,6) -> write to DataY1M05-06 table  

對於剩余的Y(1/2)Q(1-4)表也是如此

6 - 將所有雙月表拆分為單獨的月表(成本8x2x25GB = 400GB)

SELECT * FROM DataY1M002-03 WHERE month = 2 -> write to DataY1M02 table
SELECT * FROM DataY1M002-03 WHERE month = 3 -> write to DataY1M03 table
SELECT * FROM DataY1M005-06 WHERE month = 5 -> write to DataY1M05 table
SELECT * FROM DataY1M005-06 WHERE month = 6 -> write to DataY1M06 table

Y(1/2)M(XX-YY)表的其余部分也是如此

7 - 最后你有24個月度表,現在我希望你面臨的限制將會消失,所以你可以繼續你的計划 - 第二種方法讓我們說 - 進一步拆分日常表

我認為,成本方面這是最優化的方法,最終的查詢成本是
(假設計費等級1)

4x600GB + 400GB = 2800GB = $14 

當然不要忘記刪除中間表

注意:我對此計划不滿意 - 但如果將原始文件拆分為BigQuery之外的每日塊不是一個選項 - 這可以幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM