微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SQLServer 批量插入数据的两种方法

sql Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致sql一系统性能问题。下面介绍sql Server支持的两种批量数据插入方法:Bulk和表值参数(Table-Valued Parameters)。
运行下面的脚本,建立测试数据库和表值参数。

复制代码 代码如下:

--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,Pwd varchar(16))

 

下面我们使用最简单的Insert语句来插入100万条数据,代码如下: 复制代码 代码如下:

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)");//参数化sql 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 { //循环插入100万条数据,每次插入10万条,插入10次。 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(); } //每插入10万条数据后,显示此次插入所用时间

Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds",sw.ElapsedMilliseconds)); } }

 catch (Exception ex) { throw ex; }

 finally { sqlConn.Close(); }

Console.ReadLine();

耗时图如下:

使用Insert语句插入10万数据的耗时图

由于运行过慢,才插入10万条就耗时72390 milliseconds,所以我就手动强行停止了。

下面看一下使用Bulk插入的情况:

bulk方法主要思想是通过在客户端把数据都缓存在Table中,然后利用sqlBulkcopy一次性把Table中的数据插入到数据库

代码如下:

复制代码 代码如下: 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插入100万数据的耗时图

可见,使用Bulk后,效率和性能明显上升。使用Insert插入10万数据耗时72390,而现在使用Bulk插入100万数据才耗时17583。

最后再看看使用表值参数的效率,会另你大为惊讶的。

表值参数是sql Server 2008新特性,简称TVPs。对于表值参数不熟悉的朋友,可以参考最新的book online,我也会另外写一篇关于表值参数的博客,不过此次不对表值参数的概念做过多的介绍。言归正传,看代码: 复制代码 代码如下: public static void TableValuedToDB(DataTable dt) { sqlConnection sqlConn = new sqlConnection( ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString); const string TsqlStatement = "insert into BulkTestTable (Id,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; //表值参数的名字叫BulkUdt,在上面的建立测试环境的sql中有。 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",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); dt.Rows.Add(r); } sw.Start(); TableValued.TableValuedToDB(dt); sw.Stop(); Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds",sw.ElapsedMilliseconds)); }

Console.ReadLine(); }

 

耗时图如下:

使用表值参数插入100万数据的耗时图

比Bulk还快5秒。

详细出处参考:<a target="_blank" href="http://blog.csdn.net/tjvictor/article/details/4360030

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐