【進階内部資料】.NET資料批量寫入性能分析 第二篇
首先來看看,我們主要測試那些東西。因為我們本系列文章是研究SqlBulkCopy與SSIS的性能,是以,我們将他們進行詳細的對比。對于SqlBulkCopy,我們主要對它的一下幾個屬性感興趣,因為這些屬性對性能的影響很大:
Table locking:在進行批量插入資料的時候,往往會在要插入資料的表上建立一個排它鎖,一方面,這個鎖使得插入的更快;另一方面,也是的其他回話對此表的讀取等操作都進入等待。我們會使用很多不同的場景來測試這個屬性,讓大家有一個比較清晰的認識。
BatchSize:這個參數主要是定義了每次批量插入的資料條數。我們發現:沒有什麼文檔來描述這個值對性能的影響,是以,我們也會研究這個屬性值。
Use Internal Transaction:其實,很多時候,很多人對SqlBulkCopy的事務都了解有誤。我們通過很多的測試和實踐發現,如果我們在SqlBulkCopy插入資料的時候,不用事務,速度将會非常的快,當然,這個快是犧牲其他的特性為代價的。
出了測試上面的一些屬性之外,我們還會測試與批量資料的導入相關的問題,如下:
我們可以将資料導入到含有聚集索引的表和堆表中,看看哪一種表的導入速度最快,也看看如何更好的導入資料。
看看在資料導入的時候,資料庫日志檔案的使用情況。在使用批量導入資料的時候,不僅僅會寫資料檔案,還會不斷的寫日志,我們可以看看不同的設定和方式導緻日志的大小以及其他影響。
使用SQL Server Trace的Flag 610 标記可以在資料批量導入的時候使得日志記錄最小,這個Flag是否值得使用。
OK,下面我們就來準備測試環境。
首先,我們建立一個簡單的具有6個字段的表,如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=210" target="_blank"></a>
很顯然,表中的每一行資料的大小大約是320位元組。在測試的過程中,我們将會用不同的資料量來填充這個表,這個資料量會從60一直到6百萬,同時也看看相關性能的資料是否有一個線性的關系。
同時,也為了測試聚集索引表和堆表,我們也會在需要的時候建立索引,如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=211" target="_blank"></a>
我們在每次測試一個場景的時候,都會将這個表從資料庫中銷毀,然後重建。我們插入表中的資料都是采用随機生成的。另外,我們還會常見兩種基于随機值的測試:
1. 每一個Producer(也就是資料生産者)産生的每一行資料的值都是相同的,每個字段的值肯定是随機的。可能如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=212" target="_blank"></a>
2. 每一個Producer産生的每一行資料值都完全不同,類似如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=213" target="_blank"></a>
之是以要進行上面兩個測試,主要是要看看對于相同的資料的資料行在進行網絡輸入之前是否被壓縮了(因為相同的資料值多次重複的出現,這就是一個很好的壓縮的機會,可以大大的節省網絡帶寬,使得資料插入更快)。
另外,對于我們表所在的資料庫,就采用最簡單的日志模式,這也是絕大多數資料庫采用的方式。我們不會測試SqlBulkCopy的屬性與上面所有條件的所有組合,因為很多的組合的結果是可憑經驗推斷出來的,并且也不是所有的組合方式都對性能有影響。
為了使得測試更為的準确,在SqlBulkCopy進行資料的批量寫入之前,所有的資料producers都會先把資料全部準備好,之後,再将資料傳遞給SqlBulkCopy。我們關注的是SqlBulkCopy寫入性能,以及它對資料庫的影響,請記住這一點。
下面,我們就進入第一個場景:一個consumer(資料的消費者,在這裡,這個資料消費者就是SqlBulkCopy)接受6百萬條資料,然後将資料導入到一個堆表中。
通過多次測試發現,consumer執行完成的時間是56秒,同時我們這裡把Tablock和BatchSize的值設定為了0,同時我們發現日志檔案增加了6M,如圖:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=214" target="_blank"></a>
在此過程中,網絡的情況如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=215" target="_blank"></a>
我們可以看看網絡的使用大約25%(測試用的是1GB的帶寬),也就說,沒有充分的利用帶寬。
另外,CPU也顯示了隻有一個線程在運作,沒有完全的使用所有的核的功能。也就說,如果資料導入的用戶端有多個核,那麼我們可以增加SqlBulkCopy的數量,采用并行技術來導入資料,進而提高性能。
下面,我們就來測試上面的想法,如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=216" target="_blank"></a>
可以看到上面的圖,我們采用了4個SqlBulkCopy。
此時的網絡使用如下:
<a href="http://www.agilesharp.com/Services/BlogAttachment.ashx?AttachmentID=217" target="_blank"></a>
此時充分的利用了帶寬,并且速度也提升了300%。
今天就到這裡,讓大家有一個感覺!下一篇,我們接着比較更多的東西。
本文轉自yanyangtian51CTO部落格,原文連結: http://blog.51cto.com/yanyangtian/827562,如需轉載請自行聯系原作者