2017-08-12 48 views
1

我們有一個C#應用程序,每天接收一個約35,000,000行的文件。它打開文件,分別解析每條記錄,格式化一些字段,然後將一條記錄一次插入到表中。這真的很慢,這是預期的,但我被要求優化它。爲大容量單記錄插入優化MSSQL

我已經指示任何優化只能包含在SQL中。即過程或C#代碼不會發生變化。我正在嘗試提出有關如何在限制SQL修改的情況下加快此過程的想法。我有幾個想要嘗試的想法,但我也想要以前發現自己處於這種狀況的人的反饋。

想法: 1.在表上創建一個聚集索引,以便插入始終發生在文件的結尾。文件中的記錄按日期/時間排序,當前表沒有聚集索引,所以這看起來像是一種有效的方法。

  1. 以某種方式減少記錄的竊聽。這些數據本質上是不穩定的,所以能夠回滾並不是什麼大不了的事情。即使這個過程中途爆炸,他們也會重新啓動它。

  2. 更改隔離級別。也許存在一個更適合順序單記錄插入的隔離級別。

  3. 減少連接時間。 C#應用程序正在打開/關閉每個插入的連接。儘管如此,我們不能更改C#代碼,所以也許有一個技巧可以減少進行連接的開銷/時間。

我欣賞任何花時間閱讀我的文章並拋出任何他們認爲值得的想法的人。

感謝, 院長

+0

['BULK INSERT'](https://docs.microsoft.com/en-us/sql/t-sql/statements/bulk-insert-transact-sql)可能是最好的解決方案和/或定製SSIS包。 – lad2025

+1

要減少日誌開銷,如果應用程序使用單語句事務,請考慮延遲的持久性。 –

+0

刪除#1中提到的聚簇索引以外的所有索引。除了大衛提到的延遲耐久性和硬件(例如SSD上的日誌文件)之外,您可以做任何事情來減少日誌開銷。重新#3,默認的READ_COMMITTED隔離級別將表現最佳。默認連接池將緩解打開/關閉開銷;其他連接管理方法需要更改代碼。這些更改只會提供較小的性能改進。用SqlBulkCopy或表值參數可以獲得數量級的增加(每分鐘數百萬次而不是數千次)。 –

回答

0

我建議以下 - 如果可能的話。

  1. 將數據加載到臨時表中。
  2. 在SQL中進行轉換。
  3. 將數據批量插入到最終表中。

第二建議是:

  1. 修改C#代碼將數據寫入到文件中。
  2. 將文件批量插入到臨時表或最終表中。

不幸的是,您的問題是從C#到數據庫的3500萬往返。我懷疑是否有任何數據庫優化可以解決性能問題。換句話說,您需要更改C#代碼來解決性能問題。別的什麼可能只是浪費你的時間。

您可以通過使用簡單恢復或寫入臨時表來最小化日誌記錄。這些都可能有所幫助。但是,請考慮第二種選擇,因爲它對C#代碼只是一個小小的改動,可能會帶來很大的改進。

或者,如果你要做的最好的一個非常糟糕的情況:

  • 運行在同一臺服務器上的C#代碼和數據庫。確保它有很多處理器。
  • 爲數據庫添加大量SSD或內存(如果您尚未使用它)。
  • 將數據加載到僅位於SSD或內存中的表空間。
  • 將數據從本地數據庫複製到遠程數據庫。
+0

儘管我完全同意你的建議,但我無法修改過程或代碼。 – Dean

+0

但是,我將LDF移至服務器上的一個單獨驅動器,吞吐量至少提高了5倍。 – Dean