简体   繁体   English

Linq to SQL - 更新批处理

[英]Linq to SQL - Update Batch

I have the following inline SQL: 我有以下内联SQL:

    internal void UpdateWorkflowProcessingByNullToken(Guid processingToken, int numberToProcess)
    {
        string sql = string.Format(CultureInfo.InvariantCulture,
            "UPDATE TOP ({0}) Master.WorkflowEventProcessing " +
            "SET ProcessingToken = '{1}' " +
            "WHERE ProcessingToken IS NULL",
            numberToProcess, processingToken);

        this.Database.ExecuteCommand(sql);
    }

Inline SQL was used for performance. 内联SQL用于提高性能。 It was my understanding that L2S would create a SQL statement for every row that I needed to update. 据我所知,L2S会为我需要更新的每一行创建一个SQL语句。 And that was taking too long. 这花了太长时间。 Note, this was a couple of years ago. 请注意,这是几年前的事了。

Now I have a DBA telling me this: 现在我有一个DBA告诉我这个:

  • This query appears to be one of the most frequently blocking or been blocked. 此查询似乎是最频繁阻止或被阻止的查询之一。
  • This is not optimized, from database perspective, due to execution plan need to be generated for every execution. 从数据库的角度来看,这不是优化的,因为需要为每次执行生成执行计划。
  • Based on the data, this simple query is using more than 1GB of plan cache (more than 25000 copies of similar execution plans), while it could actually use only less than 50KB of memory, if only 1 copy is stored. 根据数据,这个简单的查询使用超过1GB的计划缓存(超过25000个类似的执行计划副本),而如果只存储1个副本,它实际上只能使用少于50KB的内存。
  • I would propose to create a stored procedure with the unique identifier as parameter. 我建议使用唯一标识符作为参数创建存储过程。 By design, the stored procedure (bypass compilation stage) should run faster than ad hoc query. 按照设计,存储过程(绕过编译阶段)应该比ad hoc查询运行得更快。

As developers, we've been reluctant to use stored procedures. 作为开发人员,我们一直不愿意使用存储过程。 We like having all of our data code in our C# data layer. 我们喜欢在C#数据层中拥有所有数据代码。 Am I stuck here? 我被困在这里吗? Do I need to use a stored procedure? 我需要使用存储过程吗? Or is there a way to do a mass update with L2S? 或者有没有办法用L2S进行大规模更新?

I remember reading about compiling an L2S query. 我记得读过有关编译L2S查询的内容。 I could look into that as well... 我也可以调查一下......

You can use parameterized SQL commands to execute. 您可以使用参数化SQL命令来执行。 This will generate a reusable query execution plan that will be as efficient as a stored procedure after it is initially created and cached. 这将生成可重用的查询执行计划,该计划在最初创建和缓存之后将与存储过程一样高效。 Each execution you simply supply new parameters. 每次执行都只需提供新参数。

More Details 更多细节

Given the following code that updates a demo database and a table named "Foo" 给出以下代码更新演示数据库和名为“Foo”的表

///////////////////////////////////////////////////////////
// just setup for the context for demo purposes, you would
// reference this.Database in place of creating context.
SqlConnection connection = new SqlConnection("Data Source = .; Initial Catalog = MyDb; Integrated Security = SSPI;");
var dataContext = new System.Data.Linq.DataContext(connection);
///////////////////////////////////////////////////////////

string updateQuery = "UPDATE TOP (@p1) dbo.Foo " +
"SET Data = @p2 " +
"WHERE Data IS NULL";

dataContext.Connection.Open();

var command = dataContext.Connection.CreateCommand();
command.CommandText = updateQuery;
command.CommandType = System.Data.CommandType.Text;

var param1 = new SqlParameter("@p1", System.Data.SqlDbType.Int);   
param1.Value = 3;
command.Parameters.Add(param1);

var param2 = new SqlParameter("@p2", System.Data.SqlDbType.Int);
param2.Value = 1;
command.Parameters.Add(param2);
command.Prepare();
command.ExecuteNonQuery();

param2.Value = 5;
command.ExecuteNonQuery();

From the profiler output you can see it calls sp_prepexec 从分析器输出中,您可以看到它调用sp_prepexec

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@p1 int,@p2 int',N'UPDATE TOP (@p1) dbo.Foo SET Data = @p2 WHERE Data IS NULL',@p1=3,@p2=1
select @p1

and executes the statement passing the parameters 3 and 1 then when param2.Value is set to 5 and the command executed again the profiler shows it reusing the prepared command (thus no recompiling or new execution plan generated) 并执行传递参数3和1的语句,然后当param2.Value设置为5并再次执行命令时,分析器显示它重用准备好的命令(因此不会重新编译或生成新的执行计划)

exec sp_execute 1,@p1=3,@p2=5

This is what the profiler output looks like, FYI... 这就是分析器输出的样子,仅供参考... 在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM