【发布时间】:2014-08-05 17:00:20
【问题描述】:
我有以下内联 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);
}
内联 SQL 用于提高性能。我的理解是 L2S 会为我需要更新的每一行创建一个 SQL 语句。这花了太长时间。请注意,这是几年前的事了。
现在我有一个 DBA 告诉我:
- 此查询似乎是最常被阻止或被阻止的查询之一。
- 从数据库的角度来看,这没有优化,因为每次执行都需要生成执行计划。
- 根据数据,这个简单的查询使用了超过 1GB 的计划缓存(超过 25000 个类似执行计划的副本),而如果只存储 1 个副本,它实际上只能使用不到 50KB 的内存。
- 我建议创建一个以唯一标识符作为参数的存储过程。按照设计,存储过程(绕过编译阶段)应该比即席查询运行得更快。
作为开发人员,我们一直不愿意使用存储过程。我们喜欢在 C# 数据层中包含所有数据代码。我被困在这里了吗?我需要使用存储过程吗?或者有没有办法使用 L2S 进行大规模更新?
我记得读过有关编译 L2S 查询的文章。我也可以研究一下...
【问题讨论】:
-
存储过程绝对没有问题,尤其是在正确使用的情况下。它们还允许您更新 SQL 而无需重新部署您的应用程序。
-
我同意,但是创建存储过程对我们来说开销更大。这不是关于哪种方式更好。我们决定使用 L2S,如果可能的话,我们希望将它用于所有事情。如果很难绕过这个限制,那么我们将使用存储过程。我想至少先尝试一下。
-
聪明的开发者喜欢存储过程——它工作得更快、更安全,并且在应用层和数据库层之间创建了一个清晰的 API。
-
也就是说,
numberToProcess变化很大吗?如果您将此常量设为常量,那么您将不会有多个执行计划。 -
另一个选项是将 ProcessingToken 移动到连接表中。然后,在更新令牌时,您不会阻止对 WorkflowEventProcessing 的读取。
标签: c# sql-server linq-to-sql