【发布时间】:2015-04-01 06:25:42
【问题描述】:
我们有一个 REST 服务来获取给定 ID 的成员。 SQL 单独运行很快(5 毫秒),但从 Linq 运行(使用实体框架 6)时,运行速度非常慢(230 毫秒)。
我不认为这个问题与 this、this 或 this 重复,因为它感觉与 Linq/EntityFramework 相关。
以下是统计数据: 客户端调用member get的时间约为360ms 从 C# 代码执行 Linq 查询所用的时间约为 230ms 在 SQL Server 上执行 SQL 的时间约为 228ms
生产中的 SQL 跟踪具有相似的性能(在 SQL 服务器上执行 SQL 需要 141 毫秒),因此数字感觉真实。
我尝试连续六次运行 Linq 查询,以查看从数据上下文建立连接的成本是否存在问题。这些 Linq 查询中的每一个都花费了相同的时间来运行。
如果我使用相同的数据上下文直接运行 SQL(即:Linq 生成的),运行时(从 C# 测量)从 230ms 下降到 19ms。
直接在服务器上运行 SQL(SQL Server management Studio)大约需要 5ms。
C# 代码(都在同一个例程中,使用相同的数据上下文,没有 using 块)产生这些数字:
Linq original query run =227ms
Raw SQL query: 19ms
Linq run 0=228
Linq run 1=227
Linq run 2=229
Linq run 3=229
Linq run 4=232
Linq 查询如下所示:
DateTime start = DateTime.Now;
var memberDetail = await (from member in DataContext.Members.AsNoTracking()
join memberName in DataContext.MemberNames.AsNoTracking() on member.UID equals memberName.MemberID into nameOutput
from mn in nameOutput.DefaultIfEmpty()
join memberProperty in DataContext.Properties.AsNoTracking() on member.PropertyID equals memberProperty.UID
join membershipCycle in DataContext.MembershipCycleHistories.AsNoTracking() on member.UID equals membershipCycle.MemberID into cycleOutput
from co in cycleOutput.DefaultIfEmpty()
where member.ReferenceNumber.Equals(memberNumber) &&
memberProperty.ExternalID.Equals(property, StringComparison.InvariantCultureIgnoreCase)
select new
{
member.UID,
member.Created,
member.LastUpdated,
PropertyName = memberProperty.ExternalID,
member.ReferenceNumber,
member.Active,
member.IsAwaitingSync,
member.Class,
mn.FirstName,
mn.LastName,
mn.PreferredName,
MembershipCreditBalance = co.MembershipCredits,
member.DOB
}
).FirstOrDefaultAsync();
System.Diagnostics.Trace.WriteLine(String.Format("linq run original={0}", (DateTime.Now - start).TotalMilliseconds));
而连接字符串是:
Data Source=SQLServer123;Initial Catalog=DB123;Persist Security Info=True;User ID=User123;Password=PWD123;MultipleActiveResultSets=True
【问题讨论】:
-
不要使用
DateTime.Now来执行 500 毫秒以下的计时,请使用Stopwatch类重新运行您的测试。另外,您是如何让原始 SQL 对服务器运行的,以及您是如何运行它的?最后,如果您使用 Sql Profiler,linq 查询执行服务器端需要多长时间? -
@ScottChamberlain - 我用秒表重新运行这些。结果在所提供数字的 5% 以内。 SQL 是从 linq 查询 (tostring()) 和 SQL 跟踪中提取的。直接在 management studio 中运行查询的运行时间为 5ms。
标签: performance linq entity-framework