使用ADO.Net进行SQL事务

时间:2011-02-01 06:28:59

标签: c# sql-server ado.net

我是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上执行SQL阻止

- 当我在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

3 个答案:

答案 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)

  • 对于高性能插入,请查看SqlBulkCopy类,如果它对您有效,它应该很快。
  • 正如Sean所说,使用参数化查询总是一个好主意。
  • 使用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();
    
  • 您的代码看起来不合适,您不会在每批中提交交易。您的代码不断开启新的交易。

  • 在插入大量数据时删除索引并稍后添加它们总是一个好习惯。索引会降低您的写入速度。
  • Sql Management Studio没有事务但是Sql有,试试这个:
 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 ...但是最好先确保数据是干净的(因为没有真正的错误检查/处理。