我是C#的数据库交互的新手,我试图在SqlTransaction的帮助下借助SqlCommand和SqlConnection对象在数据库中编写10000条记录并在5000之后提交。处理需要10秒。
SqlConnection myConnection = new SqlConnection("..Connection String..");
myConnection.Open();
SqlCommand myCommand = new SqlCommand();
myCommand.CommandText = "exec StoredProcedureInsertOneRowInTable Param1, Param2........";
myCommand.Connection = myConnection;
SqlTransaction myTrans = myConnection.Begintransaction();
for(int i=0;i<10000;i++)
{
mycommand.ExecuteNonQuery();
if(i%5000==0)
{
myTrans.commit();
myTrans = myConnection.BeginTransaction();
mycommand.Transaction = myTrans;
}
}
上面的代码在数据库中只给我1000行写入/秒。
但是当我尝试在SQL中实现相同的逻辑并使用SqlManagement Studio在Database上执行它时,它给了我10000次写入/秒。 当我比较上面两个approch的行为时,它告诉我在使用ADO.Net执行时会有大量的逻辑读取。
我的问题是: 1. 为什么ADO.Net执行中存在逻辑读取? Tansaction有些动摇吗? 3.为什么管理工作室无法使用它们? 4.如果我想在DB上进行非常快速的插入事务,那么将采用什么方法?
有关数据库对象的更新信息
表: tbl_FastInsertTest 没有主键,只有5个字段,前三个是int类型(F1,F2,F3),最后2个(F4,F5)是类型varchar(30)
storedprocedure:
create proc stp_FastInsertTest
{
@nF1 int,
@nF2 int,
@nF3 int,
@sF4 varchar(30),
@sF5 varchar(30)
}
as
Begin
set NoCOUNT on
Insert into tbl_FastInsertTest
{
[F1],
[F2],
[F3],
[F4],
[F5]
}
Values
{
@nF1,
@nF2,
@nF3,
@sF4,
@sF5,
} end
--------------------------------------------------------------------------------------
- 当我在SSMS上执行以下代码时,它每秒给我超过10000次写入,但当我尝试在ADO上执行相同的STP时,它每秒给我1000到1200次写入
begin trans
declare @i int
set @i=0
While(1<>0)
begin
exec stp_FastInsertTest 1,2,3,'vikram','varma'
set @i=@i+1
if(@i=5000)
begin
commit trans
set @i=0
begin trans
end
end
答案 0 :(得分:2)
如果您正在运行类似:
exec StoredProcedureInsertOneRowInTable 'blah', ...
exec StoredProcedureInsertOneRowInTable 'bloop', ...
exec StoredProcedureInsertOneRowInTable 'more', ...
SSMS中的,这是一个完全不同的场景,其中所有这些都是一个批处理。使用ADO.NET,您每次ExecuteNonQuery
都要支付一次往返 - 我实际上给它留下了深刻的印象。管理1000 / s。
重新进行逻辑读取,可以只是查看查询计划缓存,但是在不了解StoredProcedureInsertOneRowInTable
的情况下,无法评论查询特定的内容是否正在进行中。但是我怀疑你在SSMS和ADO.NET之间有一些不同的SET
条件迫使它使用不同的计划 - 这尤其是 一个问题诸如持久计算的索引列以及从sql-xml字段中“提升”的列。
让它更快 - 在这种情况下听起来像table-valued parameters就是这样,但你也应该检查other options here
答案 1 :(得分:2)
使用StringBuilder类,在单个查询中批量处理数千个INSERT语句并提交事务是一种经过验证的插入数据的方法:
var sb = new StringBuilder();
for(int i=0;i < 1000;i++) { sb.AppendFormat("INSERT INTO Table(col1,col2)
VALUES({0},{1});”,值1 [I],values2 [I]); }
sqlCommand.Text=sb.ToString();
您的代码看起来不合适,您不会在每批中提交交易。您的代码不断开启新的交易。
BEGIN TRANSACTION MyTransaction INSERT INTO Table(Col1,Col1) VALUES(Val10,Val20); INSERT INTO Table(Col1,Col1) VALUES(Val11,Val21); INSERT INTO Table(Col1,Col1) VALUES(Val12,Val23); COMMIT TRANSACTION
答案 2 :(得分:0)
您需要使用参数化查询,以便可以处理和缓存执行路径。由于您使用字符串连接(不寒而栗,这是不好的,谷歌sql注入)来构建查询,SQL Server将这10,000个查询视为单独的,单独的查询并为每个查询构建执行计划。
MSDN:http://msdn.microsoft.com/en-us/library/yy6y35y8.aspx虽然您希望稍微简化其代码,但您必须重置命令中的参数。
如果你确实想要快速获取数据库中的数据,请考虑使用bcp ...但是最好先确保数据是干净的(因为没有真正的错误检查/处理。