.NET批量大数据插入性能分析及比较(6.使用表值参数)
2015-05-06 23:31
603 查看
表值参数(Table-valued Parameter)是SQL Server 2008增加的新特性,可以将DataTable做为参数传递给存储过程。
数据库执行脚本如下
CREATE TYPE TestType AS TABLE
(
Id int NOT NULL
,Name nvarchar(20) NOT NULL
)
CREATE PROC InsertData
@rows TestType READONLY
as
begin
set nocount on
insert into TestTable(Id, Name)
select Id, Name from @rows
end
代码如下:
[c-sharp] view
plaincopy
#region 使用表值参数
public static bool ExecuteTableTypeInsert(DataTable dt, int batchSize)
{
int count = dt.Rows.Count;
bool flag = false;
SqlConnection cn = null;
SqlCommand cmd = null;
DataTable tempTable = Tools.MakeDataTable();
DataRow row = null;
try
{
cn = new SqlConnection(connectionString);
cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "InsertData";
cn.Open();
for (int i = 0; i < count; i += batchSize)
{
for (int j = i; j < i + batchSize && j < count; j++)
{
row = tempTable.NewRow();
row["Id"] = dt.Rows[j]["Id"];
row["Name"] = dt.Rows[j]["Name"];
tempTable.Rows.Add(row);
}
SqlParameter param = cmd.Parameters.AddWithValue("@rows", tempTable);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "TestType";
cmd.ExecuteNonQuery();
tempTable.Clear();
cmd.Parameters.Clear();
}
flag = true;
}
catch (Exception ex)
{
LogHelper.Error(ex.Message);
return false;
}
finally
{
if (cn != null)
{
if (cn.State == ConnectionState.Open)
{
cn.Close();
}
cn.Dispose();
}
if (cmd != null) cmd.Dispose();
}
return flag;
}
#endregion
结果如下:
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:10;Time:15312;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:20;Time:7806;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:50;Time:3767;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:100;Time:2217;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:200;Time:1743;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:400;Time:1575;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:500;Time:1566;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:600;Time:1374;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:700;Time:1286;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:800;Time:1463;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:1000;Time:1272;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:2000;Time:1069;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:4000;Time:1001;
从时间上来看,似乎并不必前面的案例强,但批处理量得增加,写性能在持续提高,而且实际上程序中花费了大量的时间在创建DataTable及填充其数据上面,如果传递给函数的就是一个DataTable集合,相信使用表值参数的表现会更好。
但考虑到需要为插入的表创建类型,创建存储过程,个人认为其通用性不是很好
数据库执行脚本如下
CREATE TYPE TestType AS TABLE
(
Id int NOT NULL
,Name nvarchar(20) NOT NULL
)
CREATE PROC InsertData
@rows TestType READONLY
as
begin
set nocount on
insert into TestTable(Id, Name)
select Id, Name from @rows
end
代码如下:
[c-sharp] view
plaincopy
#region 使用表值参数
public static bool ExecuteTableTypeInsert(DataTable dt, int batchSize)
{
int count = dt.Rows.Count;
bool flag = false;
SqlConnection cn = null;
SqlCommand cmd = null;
DataTable tempTable = Tools.MakeDataTable();
DataRow row = null;
try
{
cn = new SqlConnection(connectionString);
cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "InsertData";
cn.Open();
for (int i = 0; i < count; i += batchSize)
{
for (int j = i; j < i + batchSize && j < count; j++)
{
row = tempTable.NewRow();
row["Id"] = dt.Rows[j]["Id"];
row["Name"] = dt.Rows[j]["Name"];
tempTable.Rows.Add(row);
}
SqlParameter param = cmd.Parameters.AddWithValue("@rows", tempTable);
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "TestType";
cmd.ExecuteNonQuery();
tempTable.Clear();
cmd.Parameters.Clear();
}
flag = true;
}
catch (Exception ex)
{
LogHelper.Error(ex.Message);
return false;
}
finally
{
if (cn != null)
{
if (cn.State == ConnectionState.Open)
{
cn.Close();
}
cn.Dispose();
}
if (cmd != null) cmd.Dispose();
}
return flag;
}
#endregion
结果如下:
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:10;Time:15312;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:20;Time:7806;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:50;Time:3767;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:100;Time:2217;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:200;Time:1743;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:400;Time:1575;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:500;Time:1566;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:600;Time:1374;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:700;Time:1286;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:800;Time:1463;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:1000;Time:1272;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:2000;Time:1069;
Use SqlServer TableType Insert;RecordCount:40000;BatchSize:4000;Time:1001;
从时间上来看,似乎并不必前面的案例强,但批处理量得增加,写性能在持续提高,而且实际上程序中花费了大量的时间在创建DataTable及填充其数据上面,如果传递给函数的就是一个DataTable集合,相信使用表值参数的表现会更好。
但考虑到需要为插入的表创建类型,创建存储过程,个人认为其通用性不是很好
相关文章推荐
- .NET批量大数据插入性能分析及比较(6.使用表值参数)
- .NET批量大数据插入性能分析及比较(5.使用SqlBulkCopy)
- .NET批量大数据插入性能分析及比较(3.使用事务)
- .NET批量大数据插入性能分析及比较(5.使用SqlBulkCopy)
- .NET批量大数据插入性能分析及比较(4.使用DataAdapter批量插入)
- .NET批量大数据插入性能分析及比较(3.使用事务)
- .NET批量大数据插入性能分析及比较(4.使用DataAdapter批量插入)
- .NET批量大数据插入性能分析及比较(5.使用SqlBulkCopy)
- .NET批量大数据插入性能分析及比较(1.准备工作)
- .NET批量大数据插入性能分析及比较(2.普通插入与拼接sql批量插入)
- .NET批量大数据插入性能分析及比较(6.使用表值参数)
- NET批量大数据插入性能分析及比较
- .NET批量大数据插入性能分析及比较(2.普通插入与拼接sql批量插入)
- .NET批量大数据插入性能分析及比较(1.准备工作)
- .NET批量大数据插入性能分析及比较
- .NET批量大数据插入性能分析及比较
- MySQL大量数据插入各种方法性能分析与比较
- IO模式设置网络编程常见问题总结—IO模式设置,阻塞与非阻塞的比较,recv参数对性能的影响—O_NONBLOCK(open使用)、IPC_NOWAIT(msgrcv)、MSG_DONTWAIT(re
- IO模式设置网络编程常见问题总结—IO模式设置,阻塞与非阻塞的比较,recv参数对性能的影响—O_NONBLOCK(open使用)、IPC_NOWAIT(msgrcv)、MSG_DONTWAIT(re
- Java使用Arrays、ArrayList、LinkedList、Vector实现插入查询性能分析