我正在使用Entity Framework进行较大的查询。最近,由于超时异常,此查询失败。
当我开始调查此问题时,我使用LinqPad并直接在SSMS中复制SQL输出并运行查询。该查询将在1秒内返回!
然后查询看起来像(仅用于说明,实际查询要大得多)
DECLARE @p__linq__0 DateTime2 = '2017-10-01 00:00:00.0000000'
DECLARE @p__linq__1 DateTime2 = '2017-10-31 00:00:00.0000000'
SELECT
[Project8].[Volgnummer] AS [Volgnummer],
[Project8].[FkKlant] AS [FkKlant],
-- rest omitted for brevity
现在,我使用SQL事件探查器捕获了发送到服务器的真实SQL。该查询完全相同,不同之处在于该查询被封装在对的调用中sp_executesql
。像这样:
exec sp_executesql N'SELECT
[Project8].[Volgnummer] AS [Volgnummer],
[Project8].[FkKlant] AS [FkKlant],
-- rest omitted for brevity
',N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7)',
@p__linq__0='2017-10-01 00:00:00',@p__linq__1='2017-10-31 00:00:00'
当我在SSMS中复制/粘贴此查询时,它会运行60秒,因此在默认设置下从EF使用时会导致超时!
我无法确定为什么会出现这种差异,因为这是相同的查询,唯一的是,它的执行方式不同。
我读了很多关于EF为什么使用sp_executesql的知识,并且我理解为什么。我还读到sp_executesql与EXEC有所不同,因为它利用了queryplan缓存,但是我不明白为什么SQL优化器在为sp_executesql版本创建高效的查询计划时却如此困难,而它却能够创建高效的查询计划。直接查询版本。
我不确定完整的查询本身是否会增加问题。如果是这样,请告诉我,然后进行编辑。
多亏了提供的注释,我可以完成两件事:
DbCommandInterceptor
添加OPTION (OPTIMIZE FOR UNKNOWN)
到查询中的功能。通过将实现添加到,可以拦截由Entity Framework编译的SQL查询,然后再将其发送到服务器DbInterception
。
这样的实现很简单:
public class QueryHintInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(DbCommand command,
DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
queryHint = " OPTION (OPTIMIZE FOR UNKNOWN)";
if (!command.CommandText.EndsWith(queryHint))
{
command.CommandText += queryHint;
}
base.ReaderExecuting(command, interceptionContext);
}
}
// Add to the interception proces:
DbInterception.Add(new QueryHintsInterceptor());
由于Entity Framework也缓存查询,因此我检查是否已添加优化。
但是这种方法将拦截所有查询,而且显然不应该这样做。随着对的DbCommandInterceptionContext
访问,DbContext
我为我添加了一个具有单个属性(ISupportQueryHints
)的接口,DbContext
当查询需要此接口时,我将该接口设置为优化。
现在看起来像这样:
public class QueryHintInterceptor : DbCommandInterceptor
{
public override void ReaderExecuting(DbCommand command,
DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
var dbContext =
interceptionContext.DbContexts.FirstOrDefault(d => d is ISupportQueryHints) as ISupportQueryHints;
if (dbContext != null)
{
var queryHint = $" OPTION ({dbContext.QueryHint})";
if (!command.CommandText.EndsWith(queryHint))
{
command.CommandText += queryHint;
}
}
base.ReaderExecuting(command, interceptionContext);
}
}
在需要的地方可以用作:
public IEnumerable<SomeDto> QuerySomeDto()
{
using (var dbContext = new MyQuerySupportingDbContext())
{
dbContext.QueryHint = "OPTIMIZE FOR UNKNOWN";
return this.PerformQuery(dbContext);
}
}
因为我的应用程序利用了围绕命令和查询的基于消息的体系结构(如此处所述),所以我的实现由需要优化的查询处理程序周围的装饰器组成。必要时,此装饰器将查询提示设置为DbContext。但是,这是一个实现细节。基本思想保持不变。
问题内容: 我有两个我以为是同一意思的查询,但是我一直得到不同的结果,我希望有人可以解释这些差异如何: 1。 2。 查询的重点是查找表1中的行和val = 0而不是表2中的行。 我也使用sql server 2008,但是我怀疑这是否重要。 问题答案: 在考虑左联接时,应将它们视为具有3个概念阶段。 应用联接过滤器 左侧的行又被添加回 应用where子句。 然后,您将看到为什么得到不同结果的原因。
我刚开始使用普罗米修斯,我正在尝试理解一些事情。 我有一个Java的web应用程序,它公开了一个叫做“my_counter”的计数器。 下面的查询有什么区别? 如果我在1小时的相同时间间隔内运行这些查询,为什么两个查询返回不同的结果? 我试图实现的是看看计数器在一个可配置的时间段内增加了多少。 多谢了。 附注。我实际上使用Grafana来运行查询并选择时间范围。
上次,我发现了Java8及以上版本函数式编程的难点,并在Collectors类中发现了一个静态方法。 我们有一个类员工像: 假设我们有一个类的POJO列表,并且我们希望接收一个所有员工姓名的列表。我们有两种方法,比如: 我知道第一种方法在上使用终端操作,而第二种方法在上使用中间操作,但我想知道第一种方法的性能是否比第二种方法差,反之亦然。如果您能解释第一种情况的潜在性能下降,当我们的数据源(emp
问题内容: 有一个共识,使用接口比使用类更好。我当然同意:库法接受ArrayList替代的List将是一个废话。 也有一个共识,就是性能总是一样的。在这里,我的基准要求不同。 接口和抽象类结果都有1到4种实现。当使用两个以上的实现时,性能开始出现差异。我正在寻找这种行为的解释(以及错误共识的由来)。 问题答案: 有一个共识,使用接口比使用类更好。 这太简单了。接口和抽象类都 具有彼此之间的优势。
我计划使用NodeJS api查询大量的数据。使用流api(https://cloud.google.com/nodejs/docs/reference/firestore/0.13.x/Query?#stream)代替常规的查询获取(https://cloud.google.com/nodejs/docs/reference/firestore/0.13.x/Query?#get)有什么好处吗?
问题内容: 我正在运行以下代码,但有时在运行时会出现某种并发异常。 我对其进行了重构以解决并发问题,但这确实使我提出了一个问题。如果将for构造更改为Iterator模式,性能会有所不同吗?foreach构造和Iterator类之间的访问级别有什么区别? 问题答案: 区别主要在于语法糖,不同之处在于可以从迭代中删除项目。从技术上讲,增强的循环使您可以循环遍历所有,其中至少包括s和数组。 不必担心性