這是導入大量數據並分解為 ETL 的好策略嗎?
我有一組五個表(如果我理解命名法的話,這是一個高度分解的 ETL 模式),我將通過批量導入載入它們,然後將這五個表中的一些插入執行到其他表的 SLEW 中,包括插入只依賴我剛剛插入到第一個表中的值。
我可以將插入作為 A、B、C 程序進行,在其中插入到第一個表中,然後插入到存在於 A + T 中的某個表 S 中(作為已預載入“配置數據”的其他表),然後插入到存在於 B + U 等中的 Z 中。
我應該嘗試用游標批處理這些插入(我知道,扔掉叛徒)還是應該只執行原始
insert into
腳本並讓伺服器死於一千次熱死?基本上我擔心伺服器會餓死或導致它因過多的索引或其他插入內容而崩潰。我應該將插入內容分階段為:
- 插入一組表
- 根據第一個表插入輔助表
- 插入三級表等。
或者我應該插入到所有需要數據的故事中,但通過游標以一次 100k 行的“for循環”樣式模式進行。
FWIW,這是我在上一份工作中從 DBA 那裡看到的一種行為,所以我認為這是“我應該做的”(通過游標的批處理),但也許我對他們在做什麼還不夠了解(他們還實時載入到已經有數據的系統中,然後再載入新數據)。
還要記住,我通常是 C# 開發人員,但我在這裡擁有最多的 TSQL 經驗,我正在努力做出最好的過程來原始載入這些數據,而不是我們的“目前”方法主要是 webservice fetches 和 NHibernate save-commits。
我認為對這個問題很重要的事情:
- 當我這樣做時,此伺服器上不會有其他負載,我將完全控制盒子,我是這裡唯一感興趣的使用者(這是在其他人可以對盒子做任何事情之前的初始數據載入)
- 在所有表上都有索引,如果合適,還有 FK 和其他謂詞
- 整個數據庫系統現在正在用於大量其他客戶端,所以我知道操作需要索引,但是如果我應該做一些事情來禁用它們並重新啟用它們以使插入等更快,我正在尋找對於那些優化技巧。
- 我正在等待樣本數據,但我希望給定表中的最大記錄約為一百萬行,相當寬,並且我將在其他表中插入最多一百萬行的輔助表來到二級或三級。
- 硬體是“平均的”。
如果您對導入數據的完整性有信心,最好在開始插入之前禁用對數據庫的所有約束,然後在事後重新啟用它們。
不久前請參閱這個有用的堆棧溢出答案:Can Foreign key constraints are暫時禁用使用T-SQL?
這將使您不必擔心分層插入以尊重您正在載入的數據庫的現有約束。
就實際插入本身而言,我會不使用游標。該過程不僅速度慢,而且會佔用大量記憶體並創建數據庫鎖。如果您在非常大量的行中進行游標,您還會冒著快速增加數據庫日誌大小的風險。如果伺服器只是一個普通的伺服器,那麼空間最終可能是一個問題。在執行您的流程所需的額外插入時,請嘗試考慮更多基於集合的方法。
例如,如果您可以這樣做:
insert into t1 (col1) SELECT col1 FROM t2
而不是這個:
... insert into t1 (col1) values ('foo'); insert into t1 (col1) values ('bar'); insert into t1 (col1 values ...
我個人會使用 SSIS 來完成這項任務。首先,我將批量插入臨時表或使用數據流,然後執行所需的任何清理和轉換任務,並將轉換後的數據載入到最終的一組臨時表中。然後使用數據流任務將數據發送到生產表。我有兩組單獨的臨時表,一組包含原始數據,一組包含轉換後的數據的原因是,它可以更容易地研究隨著時間的推移執行導入而出現的數據問題,以及轉換是否在最終負載,那麼影響產品的最終負載會更快。注意數據流中的 SSIS 確實一次處理一條記錄,但它的處理速度比普通游標快得多,尤其是在您此時沒有進行數據轉換的情況下。進一步在 SSIS 中,