生活随笔
收集整理的這篇文章主要介紹了
SQL Server 批量插入数据的两种方法(转)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文:http://blog.csdn.net/tjvictor/article/details/4360030
????? 在SQL Server 中插入一條數據使用Insert語句,但是如果想要批量插入一堆數據的話,循環使用Insert不僅效率低,而且會導致SQL一系統性能問題。下面介紹 SQL Server支持的兩種批量數據插入方法:Bulk和表值參數(Table-Valued Parameters)。
運行下面的腳本,建立測試數據庫和表值參數。
[c-sharp] view plaincopy
--Create?DataBase??create?database?BulkTestDB;??go??use?BulkTestDB;??go??--Create?Table??Create?table?BulkTestTable(??Id?int?primary?key,??UserName?nvarchar(32),??Pwd?varchar(16))??go??--Create?Table?Valued??CREATE?TYPE?BulkUdt?AS?TABLE????(Id?int,?????UserName?nvarchar(32),?????Pwd?varchar(16))?? ?
下面我們使用最簡單的Insert語句來插入100萬條數據,代碼如下:
[c-sharp] view plaincopy
Stopwatch?sw?=?new?Stopwatch();????SqlConnection?sqlConn?=?new?SqlConnection(??????ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);????SqlCommand?sqlComm?=?new?SqlCommand();??sqlComm.CommandText?=?string.Format("insert?into?BulkTestTable(Id,UserName,Pwd)values(@p0,@p1,@p2)");??sqlComm.Parameters.Add("@p0",?SqlDbType.Int);??sqlComm.Parameters.Add("@p1",?SqlDbType.NVarChar);??sqlComm.Parameters.Add("@p2",?SqlDbType.VarChar);??sqlComm.CommandType?=?CommandType.Text;??sqlComm.Connection?=?sqlConn;??sqlConn.Open();??try??{????????????for?(int?multiply?=?0;?multiply?<?10;?multiply++)??????{??????????for?(int?count?=?multiply?*?100000;?count?<?(multiply?+?1)?*?100000;?count++)??????????{????????????????sqlComm.Parameters["@p0"].Value?=?count;??????????????sqlComm.Parameters["@p1"].Value?=?string.Format("User-{0}",?count?*?multiply);??????????????sqlComm.Parameters["@p2"].Value?=?string.Format("Pwd-{0}",?count?*?multiply);??????????????sw.Start();??????????????sqlComm.ExecuteNonQuery();??????????????sw.Stop();??????????}????????????????????Console.WriteLine(string.Format("Elapsed?Time?is?{0}?Milliseconds",?sw.ElapsedMilliseconds));??????}??}??catch?(Exception?ex)??{??????throw?ex;??}??finally??{??????sqlConn.Close();??}????Console.ReadLine();?? 耗時圖如下:
由于運行過慢,才插入10萬條就耗時72390 milliseconds,所以我就手動強行停止了。
?
下面看一下使用Bulk插入的情況:
bulk方法主要思想是通過在客戶端把數據都緩存在Table中,然后利用SqlBulkCopy一次性把Table中的數據插入到數據庫
代碼如下:
[c-sharp] view plaincopy
public?static?void?BulkToDB(DataTable?dt)??{??????SqlConnection?sqlConn?=?new?SqlConnection(??????????ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);??????SqlBulkCopy?bulkCopy?=?new?SqlBulkCopy(sqlConn);??????bulkCopy.DestinationTableName?=?"BulkTestTable";??????bulkCopy.BatchSize?=?dt.Rows.Count;????????try??????{??????????sqlConn.Open();??????if?(dt?!=?null?&&?dt.Rows.Count?!=?0)??????????bulkCopy.WriteToServer(dt);??????}??????catch?(Exception?ex)??????{??????????throw?ex;??????}??????finally??????{??????????sqlConn.Close();??????????if?(bulkCopy?!=?null)??????????????bulkCopy.Close();??????}??}????public?static?DataTable?GetTableSchema()??{??????DataTable?dt?=?new?DataTable();??????dt.Columns.AddRange(new?DataColumn[]{??????????new?DataColumn("Id",typeof(int)),??????????new?DataColumn("UserName",typeof(string)),??????new?DataColumn("Pwd",typeof(string))});????????return?dt;??}????static?void?Main(string[]?args)??{??????Stopwatch?sw?=?new?Stopwatch();??????for?(int?multiply?=?0;?multiply?<?10;?multiply++)??????{??????????DataTable?dt?=?Bulk.GetTableSchema();??????????for?(int?count?=?multiply?*?100000;?count?<?(multiply?+?1)?*?100000;?count++)??????????{??????????????DataRow?r?=?dt.NewRow();??????????????r[0]?=?count;??????????????r[1]?=?string.Format("User-{0}",?count?*?multiply);??????????????r[2]?=?string.Format("Pwd-{0}",?count?*?multiply);??????????????dt.Rows.Add(r);??????????}??????????sw.Start();??????????Bulk.BulkToDB(dt);??????????sw.Stop();??????????Console.WriteLine(string.Format("Elapsed?Time?is?{0}?Milliseconds",?sw.ElapsedMilliseconds));??????}????????Console.ReadLine();??}?? 耗時圖如下:
可見,使用Bulk后,效率和性能明顯上升。使用Insert插入10萬數據耗時72390,而現在使用Bulk插入100萬數據才耗時17583。
?
最后再看看使用表值參數的效率,會另你大為驚訝的。
?
表值參數是SQL Server 2008新特性,簡稱TVPs。對于表值參數不熟悉的朋友,可以參考最新的book online,我也會另外寫一篇關于表值參數的博客,不過此次不對表值參數的概念做過多的介紹。言歸正傳,看代碼:
[c-sharp] view plaincopy
public?static?void?TableValuedToDB(DataTable?dt)??{??????SqlConnection?sqlConn?=?new?SqlConnection(????????ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString);??????const?string?TSqlStatement?=???????"insert?into?BulkTestTable?(Id,UserName,Pwd)"?+???????"?SELECT?nc.Id,?nc.UserName,nc.Pwd"?+???????"?FROM?@NewBulkTestTvp?AS?nc";??????SqlCommand?cmd?=?new?SqlCommand(TSqlStatement,?sqlConn);??????SqlParameter?catParam?=?cmd.Parameters.AddWithValue("@NewBulkTestTvp",?dt);??????catParam.SqlDbType?=?SqlDbType.Structured;????????????catParam.TypeName?=?"dbo.BulkUdt";??????try??????{????????sqlConn.Open();????????if?(dt?!=?null?&&?dt.Rows.Count?!=?0)????????{????????????cmd.ExecuteNonQuery();????????}??????}??????catch?(Exception?ex)??????{????????throw?ex;??????}??????finally??????{????????sqlConn.Close();??????}??}????public?static?DataTable?GetTableSchema()??{??????DataTable?dt?=?new?DataTable();??????dt.Columns.AddRange(new?DataColumn[]{????????new?DataColumn("Id",typeof(int)),????????new?DataColumn("UserName",typeof(string)),????????new?DataColumn("Pwd",typeof(string))});????????return?dt;??}????static?void?Main(string[]?args)??{??????Stopwatch?sw?=?new?Stopwatch();??????for?(int?multiply?=?0;?multiply?<?10;?multiply++)??????{??????????DataTable?dt?=?TableValued.GetTableSchema();??????????for?(int?count?=?multiply?*?100000;?count?<?(multiply?+?1)?*?100000;?count++)??????????{??????????????????????DataRow?r?=?dt.NewRow();??????????????r[0]?=?count;??????????????r[1]?=?string.Format("User-{0}",?count?*?multiply);??????????????r[2]?=?string.Format("Pwd-{0}",?count?*?multiply);??????????????dt.Rows.Add(r);??????????}??????????sw.Start();??????????TableValued.TableValuedToDB(dt);??????????sw.Stop();??????????Console.WriteLine(string.Format("Elapsed?Time?is?{0}?Milliseconds",?sw.ElapsedMilliseconds));??????}????????Console.ReadLine();??}?? 耗時圖如下:
比Bulk還快5秒。
?
如需轉載,請注明此文原創自CSDN TJVictor專欄:http://blog.csdn.net/tjvictor/archive/2009/07/18/4360030.aspx
轉載于:https://www.cnblogs.com/tonykan/archive/2013/05/25/3098750.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的SQL Server 批量插入数据的两种方法(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。