2017-09-03 166 views
2

我有一個數據的CSV:「更新」的好習慣?

ID, Name, Address, Date 
1 , Paul, Fake 123,2017-01-01 

我上傳文件到一個新的表(即「用戶」)

幾個月後,我收到一個CSV與該表的插入和更新。即

ID, Name, Address, Date 
1 , Paul, Fake 999,2017-06-01 
2 , Joe , Foo 123 ,2017-06-01 
... 

如果這是一個普通的SQL數據庫,我做了一個Upsert(就像在Mysql中替換一樣)。但是在BigQuery中做到這一點的最佳模式是什麼?更新的DML配額限制是96%的表,太小,無法:(。

我在「交易」表想了想,「最終」表。

當我有一個新的文件,我可以上傳到Transactional表中,然後我可以執行一個查詢,獲得每個「ID」的最後一個值,並將這些數據放入「Final」表中。顯然,查詢的選項是「writeDisposition:WRITE_TRUNCATE」擦除舊數據。

我認爲這是一個混亂的解決方案,但我不能找到一個更好的辦法,有人知道如何做到這一點更好?有什麼地方讀「設計模式」可供BigQuery?

+1

我希望別人可以寫一個完整的答案,但常見的解決方案是每天有一個附加表和邏輯視圖。對於當天,邏輯視圖選擇每個維度中的最新值。在一天結束時,運行更新查詢來修復重複項,然後將邏輯視圖更改爲僅當天的「SELECT *」。確保爲視圖定義使用標準SQL。 –

回答

1

幾個音符,

  • 我假設,在數據的變化是相對於目標數據大到足以覆蓋目標表。例如,如果您擁有幾百條有十億條記錄的目標表的更改記錄,則不希望採用這種方法。
  • 此外,查詢可能需要對分區表進行一些更改。
  • 作爲副作用,這將從目標表中刪除任何重複記錄。所以您需要仔細選擇用於識別記錄更改的列。

使用連接和登陸表:與需要被合併到目標表的更改數據源

讓我們調用表。

SELECT SRC.Id as Id, 
     SRC.Name as Name, 
     SRC.Address as Address, 
     SRC.Date as Date 
FROM SourceTable SRC 
    LEFT OUTER JOIN TargetTable TGT 
USING (Id) 
WHERE TGT.Id IS NULL 

UNION DISTINCT 

SELECT CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Id ELSE TGT.Id END AS Id, 
     CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Name ELSE TGT.Name END AS Name, 
     CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Address ELSE TGT.Address END AS Address, 
     CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Date ELSE TGT.Date END AS Date 
FROM SourceTable SRC 
    RIGHT OUTER JOIN TargetTable TGT 
USING (Id) 

現在,您可以在目標表上使用WRITE_TRUNCATE運行上述查詢。 我沒有測試過這個特定的查詢,但方法很好。查詢的複雜性可以通過BigQuery中的一些編碼或UDF來減少。績效很大程度上取決於變更數據的大小和性質。

我希望這會有所幫助。