【高級內部資料】.NET數據批量寫入性能分析 第一篇
說起數據的批量寫入,相信大家應該不陌生了,那么我們本系列的文章不准備講述如何來進行數據的批量寫入,而是介紹常用的數據批量寫入方法的性能分析。
同時,本篇問題的目的不是告訴大家,何種方式最好(很多人喜歡問“什么是最好的”,在技術中沒有所謂的最好的技術,一切都要情況而定),而是給大家一些數據,讓大家知道各種不同的情況對性能的影響,從而幫助大家更好地進行抉擇。
在.NET環境中,數據批量寫入的方式有很多,大家隨便上面找一下就可以找到一大堆。在眾多的數據批量寫入方式中,SqlBulkCopy與SSIS是用的比較多,也是相對而言比較成熟的方案。
也許大家認為SqlBulkCopy我用過,那么,這里就有幾個問題大家可以在心里想一想是否可以明確的回答:
- 如何設置SqlBulkCopy的各個屬性的,是否確切的直到每一個屬性對寫入性能的影響,而不是憑感覺。
- 寫入的數據量是多少?到底何為批量?1000?100萬?還是?
- 不同級別的數據寫入對CPU,網絡,磁盤的影響?
- 寫入的時候,數據庫的性能如何?是否被寫死了?還是我們以為“數據庫會管理好這一切的”
……
還有更多的問題,這里就不在羅列了。那么,我們本系列將會對它們進行深入的對比,如果大家對它們不是很熟悉,可以借此機會學習一下,批量數據的寫入操作是每個.NET技術人員都要掌握的技能之一。
SqlBulkCopy是隨着.NET Framework 2.0而發布的類,其實SqlBulkCopy就是一個.NET與數據庫BULK Insert命令的一個接口。
當我們調用SqlBulkCopy的方法和設置相關的屬性的時候,這些都會以BULK Insert命令發送給數據庫去執行。SqlBulkCopy有很多的屬性,而這些屬性的設置可以在不同的程度上面影響數據寫入的性能。我們本系列文章不會詳細的講述如何使用SqlBulkCopy類,而是講述一些我們關心的屬性設置(不會把所以的屬性設置全部講完)。
學習本系列文章,因為不是初級的文章,希望大家有一下的技術背景:
- 對.NET知識有比較扎實的理解
- 掌握.NET的並行編程相關的知識
- 如果對SQL Server的內核有一定的認識那就更好了
下面,我們就進入正題。
在把數據從一個地方加載到另外的一個地方的時候,常常會用到Producer/Consumer模式,流程如下(中文理解為:生產與消費模式,這個中文的理解有點怪,以后我們直接就用英文稱呼):
- Producer(生產者)從指定的數據源中獲取數據(數據源可以是任何的形式,例如文本,XML,數據庫,甚至是其他提供數據的服務接口等)
- 如果有需要,Producer對數據進行相關的操作
- Producer將數據傳遞給Consumer,然后Consumer將數據寫入到指定的目標源中。
簡單的理解就是:Producer提供數據,Consumer使用數據。
如果大家對SSIS有所了解的話,應該很好理解上面的這種模式。很多的時候,當我們對數據進行傳輸,轉換等操作的時候,SSIS倒是一個非常不多的工具(SSIS在實際中也是非常常用的,可能在國內用的少一點)。當然,除此之外,我們還可以寫.NET的代碼來進行上述的操作,特別是當數據轉換的操作和邏輯特別復雜的時候。
另外,在使用Producer/Consumer模式的時候,我們可以充分的利用多核計算機的能力,使用並行編程來提升性能:使用多個Producer來並行的加載數據,然后將數據傳遞給多個Consumer,從而使得數據的讀取,轉換,寫入的負載分擔在多個核上面。
注意:Producer與Consumer不是一一對應的關系,即不是每個Producer,非得有一個Consumer
用下面的一個圖就可以說明這個問題:
對於SqlBulkCopy而言,不是非常適合提到的上面提到的“Producer/Consumer模式” ,因為我們在用SqlBulkCopy將數據寫入的時候,直接調用的是WriteToServer方法將數據以一定的形式(DataTable或者DataReader等)寫入到了數據庫,沒有一個明確的Consumer,如果真有,那也是目標數據源了,這個時候Producer就和Consumer是個一一對應的關系了。在這種情況下,如果我們要產生了10個Producer,之后要使用一個Consumer將數據寫入(或者少於10的Consumer),那么,我們就需要做更多的事情來克服SqlBulkCopy的限制了。
在我們接下來的性能分析中,我們將會克服上面說的那個限制:我們自己來實現一個繼承了IDataReader接口的緩沖對象,這個對象可以用來進行很多的復雜的數據操作,而SqlBulkCopy將會把我們自己實現的緩沖對象當成是DataReader來獲取數據。實現如圖所示:
采用了上面的實現之后,我們就可以實現這樣的方式:
- 使用多個Producer將數據發送給多個Consumer
- 一個Producer將數據發送給多個Consumer
- 多個Producer將數據發送給一個Consumer
同時有一點需要注意的就是:如果數據的Producer和Consumer同時運行,那么會使用很多的內存,並且Producer和Consumer越多,內存使用的越多,因為數據都是在處理的時候都放在內存中的,一直到最后將數據寫入到數據庫等地方,此時內存就會被釋放。
由於時間的限制,我們暫時就嘮叨到這里!下一篇,我們就來看看如何進行性能的分析!
系列文章鏈接:
IIS負載均衡-Application Request Route詳解第一篇: ARR介紹
IIS負載均衡-Application Request Route詳解第二篇:創建與配置Server Farm
IIS負載均衡-Application Request Route詳解第三篇:使用ARR進行Http請求的負載均衡(上)
IIS負載均衡-Application Request Route詳解第三篇:使用ARR進行Http請求的負載均衡(下)
IIS負載均衡-Application Request Route詳解第四篇:使用ARR實現三層部署架構
查詢優化器內核剖析第一篇
查詢優化器內核剖析第二篇:產生候選執行計划&執行計划成本估算
查詢優化器內核剖析第三篇:查詢的執行與計划的緩存 & Hint提示
查詢優化器內核剖析第四篇:從一個實例看執行計划
查詢優化器內核剖析第七篇:執行引擎之數據訪問操作---Scan
查詢優化器內核剖析第八篇:執行引擎之數據訪問操作---Seek(上)
查詢優化器內核剖析第八篇:執行引擎之數據訪問操作---Seek(下)