2009-08-05 77 views
3

我正在做日誌文件的ETL到PostgreSQL數據庫,並且想了解更多關於用於優化將數據加載到簡單的星型模式中的性能的各種方法。SQL - 優化批量插入和大型連接的性能?

擺在上下文中的問題,下面是我目前做一個概述:

  1. 刪除所有外鍵和唯一 約束
  2. 導入數據(約100萬條記錄)
  3. 回覆 - 創建約束並在事實表上運行分析。

導入數據是通過從文件加載完成的。對於每一個文件:

1)利用COPY從數據加載到臨時表(PostgreSQL的大量上傳工具)

2)更新每個9代維表的使用的插入對於每個這樣的任何新的數據如:

INSERT INTO host (name) 
SELECT DISTINCT host_name FROM temp_table 
EXCEPT 
SELECT name FROM host; 
ANALYZE host; 

的Analyze在擁有超過千萬的更新的過程中保持統計最新(的想法INSERT結束時運行這是可取的或必要的最低它不?似乎會顯着降低性能)。

3)事實表,然後用邪惡的9路更新加入:

INSERT INTO event (time, status, fk_host, fk_etype, ...) 
SELECT t.time, t.status, host.id, etype.id ... 
FROM temp_table as t 
JOIN host ON t.host_name = host.name 
JOIN url ON t.etype = etype.name 
... and 7 more joins, one for each dimension table 

是否有更好的方法我俯瞰?

回答

1

我嘗試了幾種不同的方法來試圖規範化來自源的數據傳入,因此通常我已經找到了您現在使用的方法來作爲我的選擇。它容易遵循和輕微的變化保持輕微。嘗試在階段2期間從維度表中返回生成的標識僅僅是複雜的事情,並且通常會生成太多的小型查詢以便對大型數據集有效。在現代版本中,Postgres應該非常有效地使用「unholy join」,並且使用「選擇不同的除了select」對我很好。其他人可能會更好地瞭解,但我發現你現在的方法是我的推薦方法。

0

在第2階段你知道你將數據插入到(你插入後),每個維度的主鍵,但你扔掉該信息,並重新發現它在第3階段您「邪惡」的9路加入。

相反,我建議創建一個插入到事實表中的sproc;例如insertXXXFact(...),它按照命名約定getOrInsertXXXDim調用其他一些sprocs(每個維度一個),其中XXX是有問題的維度。每個sprocs將查找或爲給定維度插入一個新行(從而確保參照完整性),並應返回事實表應引用的維度的主鍵。這將顯着減少您在第3階段需要完成的工作,該階段現在縮減爲表格的調用insert into XXXFact values (DimPKey1, DimPKey2, ... etc.)

我們在getOrInsertXXX sprocs中採用的方法是如果沒有可用的值插入虛擬值並有一個單獨的清理流程,以便稍後識別和豐富這些值。

+1

我原則上同意,但是當我嘗試這種方法時,我發現它平均慢了50%。它看起來像維度表的緩存結合做大量操作(而不是單獨的選擇/插入)更快。 – Rob 2009-08-05 19:19:20

+1

@Rob:這很有趣,因爲它是一種過去爲我工作的方法。順便說一句,我不能相信這個答案沒有任何評論downvoted! – Adamski 2009-08-12 09:52:34