gpt4 book ai didi

c# - Ef Linq 查询超时,但相同的查询在 SSMS 上不到 1 秒

转载 作者:太空狗 更新时间:2023-10-29 20:27:03 26 4
gpt4 key购买 nike

首先,我在 SSMS 上尝试了 ARITHABORT OFF,它仍然不到 1 秒。

我使用 EntityFrameWork:6.1.3 和 Azure Sql S1 层(我会尝试使用第 3 层,如果有变化会通知您。)

我使用 EF Profiler 从 linq 获取生成的 sql。我已经查询了我共享的所有 linq,它们在 SSMS 上都不到 1 秒。

我在 AuditLog 表上有 300 万条记录。 ID 为 3 的一位客户有 170K 条记录,另一位 ID 为 35 的客户有 125 条记录。我将最小化代码。

审计日志模型:

 public class AuditLog
{
public long? CustomerId { get; set; }

[ForeignKey("CustomerId")]
public virtual CustomerSummary Customer { get; set; }

[Required]
[Index]
public DateTime CreatedDate { get; set; }
}

第一次查询:

 if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}

如果我尝试与拥有 170k 行的客户一起尝试,它会给出超时异常。如果我对有 125 条记录的客户进行尝试,没问题。

第二个查询:与第一个查询相同,我只包括客户。

if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}

结果与第一个查询相反。如果我尝试与拥有 170k 行的客户一起使用,那很好。如果我尝试与有 125 条记录的客户一起尝试,它会给出超时异常。

第三个查询:与第一个查询相同,但我在 customerId 的位置匹配 long?

 if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}

结果与第一个查询相反。如果我尝试与拥有 170k 行的客户一起使用,那很好。如果我尝试与有 125 条记录的客户一起尝试,它会给出超时异常。

第四个查询:与第二个查询相同,但我在 customerId 的位置匹配 long?

 if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}

结果与第二个查询相反。如果我尝试与拥有 170k 行的客户一起尝试,它会给出超时异常。如果我对有 125 条记录的客户进行尝试,没问题。

我真的很困惑。为什么内部连接或将匹配参数更改为 long? 会改变结果?为什么所有这些查询在 SSMS 上运行不到 1 秒并在 ef linq 上给出错误?

错误:

{System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)

更新(19/04/2016):

Ivan Stoev 之后意见建议。

Have you tried (just for the sake of test) using hardcoded 3 and 35 instead of customerId variable?

我没有收到任何错误,查询速度与在 SSMS 上一样快。

更新(2016 年 4 月 20 日):真正的问题是参数嗅探。当我将参数包含或更改为可为空时,实际上我已经创建了另一个查询和另一个查询计划。我为拥有 125 条记录的客户创建了一些计划,为拥有这 4 个查询的 170k 记录的客户创建了其他计划。这就是我得到不同结果的原因。

最佳答案

您遇到的是所谓的 Parameter Sniffing Problem 的结果。 .到目前为止,我还不知道一个简单的通用解决方案,因此通常建议通过在表达式中手动绑定(bind)常量值来消除一些 SQL 查询参数来提出解决方法,例如 EntityFramework LINQ query count fails but query returns result. How to optimize LINQ query? .

对于您的场景,我建议使用以下自定义扩展方法:

public static class QueryableExtensions
{
public static IQueryable<T> WhereEquals<T, TValue>(this IQueryable<T> source, Expression<Func<T, TValue>> selector, TValue value)
{
var predicate = Expression.Lambda<Func<T, bool>>(
Expression.Equal(selector.Body, Expression.Constant(value)),
selector.Parameters);
return source.Where(predicate);
}
}

然后像这样更新你的代码段

if (customer != null)
{
var result= Dbset.WhereEquals(x => x.CustomerId.Value, customer.Id)
.OrderByDescending(x => x.CreatedDate)
.Skip(0).Take(25)
.Include(x => x.Customer)
.ToList();
}

关于c# - Ef Linq 查询超时,但相同的查询在 SSMS 上不到 1 秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36698792/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com