【发布时间】:2021-11-13 12:44:57
【问题描述】:
我继承了一个代码库,但我在 Entity Framework Core v3.1.19 中遇到了一个奇怪的问题。
Entity Framework 正在生成以下查询(在 SQL Server Profiler 中找到),它需要将近 30 秒才能运行,而在 SSMS 中运行相同的代码(再次取自探查器)需要 1 秒(这是一个示例,但从数据库中获取数据时,整个站点的运行速度极慢)。
exec sp_executesql N'SELECT [t].[Id], [t].[AccrualLink], [t].[BidId], [t].[BidId1], [t].[Cancelled], [t].[ClientId], [t].[CreatedUtc], [t].[CreatorUserId], [t].[Date], [t].[DeletedUtc], [t].[DeleterUserId], [t].[EmergencyContact], [t].[EmergencyName], [t].[EmergencyPhone], [t].[EndDate], [t].[FinalizerId], [t].[Guid], [t].[Invoiced], [t].[IsDeleted], [t].[Notes], [t].[OfficeId], [t].[PONumber], [t].[PlannerId], [t].[PortAgencyAgentEmail], [t].[PortAgencyAgentName], [t].[PortAgencyAgentPhone], [t].[PortAgencyId], [t].[PortAgentId], [t].[PortId], [t].[PortType], [t].[PositionNote], [t].[ProposalLink], [t].[ServiceId], [t].[ShipId], [t].[ShorexAssistantEmail], [t].[ShorexAssistantName], [t].[ShorexAssistantPhone], [t].[ShorexManagerEmail], [t].[ShorexManagerName], [t].[ShorexManagerPhone], [t].[ShuttleBus], [t].[ShuttleBusEmail], [t].[ShuttleBusName], [t].[ShuttleBusPhone], [t].[ShuttleBusServiceProvided], [t].[TouristInformationBus], [t].[TouristInformationEmail], [t].[TouristInformationName], [t].[TouristInformationPhone], [t].[TouristInformationServiceProvided], [t].[UpdatedUtc], [t].[UpdaterUserId], [t].[Water], [t].[WaterDetails], [t0].[Id], [t0].[CreatedUtc], [t0].[CreatorUserId], [t0].[DeletedUtc], [t0].[DeleterUserId], [t0].[Guid], [t0].[IsDeleted], [t0].[LanguageId], [t0].[Logo], [t0].[Name], [t0].[Notes], [t0].[OldId], [t0].[PaymentTerms], [t0].[Pricing], [t0].[Services], [t0].[Status], [t0].[UpdatedUtc], [t0].[UpdaterUserId], [t1].[Id], [t1].[CreatedUtc], [t1].[CreatorUserId], [t1].[DeletedUtc], [t1].[DeleterUserId], [t1].[Guid], [t1].[IsDeleted], [t1].[Name], [t1].[OldId], [t1].[UpdatedUtc], [t1].[UpdaterUserId], [s].[Id], [s].[CreatedUtc], [s].[CreatorUserId], [s].[DeletedUtc], [s].[DeleterUserId], [s].[Guid], [s].[IsDeleted], [s].[Name], [s].[Pax], [s].[UpdatedUtc], [s].[UpdaterUserId]
FROM (
SELECT [o].[Id], [o].[AccrualLink], [o].[BidId], [o].[BidId1], [o].[Cancelled], [o].[ClientId], [o].[CreatedUtc], [o].[CreatorUserId], [o].[Date], [o].[DeletedUtc], [o].[DeleterUserId], [o].[EmergencyContact], [o].[EmergencyName], [o].[EmergencyPhone], [o].[EndDate], [o].[FinalizerId], [o].[Guid], [o].[Invoiced], [o].[IsDeleted], [o].[Notes], [o].[OfficeId], [o].[PONumber], [o].[PlannerId], [o].[PortAgencyAgentEmail], [o].[PortAgencyAgentName], [o].[PortAgencyAgentPhone], [o].[PortAgencyId], [o].[PortAgentId], [o].[PortId], [o].[PortType], [o].[PositionNote], [o].[ProposalLink], [o].[ServiceId], [o].[ShipId], [o].[ShorexAssistantEmail], [o].[ShorexAssistantName], [o].[ShorexAssistantPhone], [o].[ShorexManagerEmail], [o].[ShorexManagerName], [o].[ShorexManagerPhone], [o].[ShuttleBus], [o].[ShuttleBusEmail], [o].[ShuttleBusName], [o].[ShuttleBusPhone], [o].[ShuttleBusServiceProvided], [o].[TouristInformationBus], [o].[TouristInformationEmail], [o].[TouristInformationName], [o].[TouristInformationPhone], [o].[TouristInformationServiceProvided], [o].[UpdatedUtc], [o].[UpdaterUserId], [o].[Water], [o].[WaterDetails]
FROM [OpsDocuments] AS [o]
WHERE ([o].[IsDeleted] <> CAST(1 AS bit)) AND ((CASE
WHEN [o].[Cancelled] = CAST(0 AS bit) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END & CASE
WHEN [o].[Invoiced] = CAST(0 AS bit) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END) = CAST(1 AS bit))
ORDER BY [o].[Date]
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY
) AS [t]
LEFT JOIN [TourClients] AS [t0] ON [t].[ClientId] = [t0].[Id]
LEFT JOIN [TourLanguages] AS [t1] ON [t0].[LanguageId] = [t1].[Id]
LEFT JOIN [Ships] AS [s] ON [t].[ShipId] = [s].[Id]
ORDER BY [t].[Date]',N'@__p_0 int,@__p_1 int',@__p_0=0,@__p_1=10
此查询从可能的 55 行中返回 10 行,所以没有说大数字或其他任何内容。
起初我认为这可能是转换时的数据类型问题,但检查所有数据类型它们都是正确的,并且由于问题显示在分析器中,我假设这是一个 SQL 问题,而不是具体的实体框架。但是,在探查器中运行时,我找不到两者之间的任何区别,除了来自 EF 的那个只需要 30 倍的时间。
希望有人可以建议在哪里看。
编辑:感谢 cmets 中的所有建议。至于 Linq 和可重现的示例,这将是棘手的,因为该项目的代码库是一些奇怪的自制自动生成系统。您给它一个带有大量自定义属性的 ViewModel,它会尝试为您做所有事情(如此多的抽象层),因此很难找到任何东西。 听起来我将不得不开始将这些重写为更有限的控制器。
【问题讨论】:
-
TL;DR 可能是参数嗅探。见Slow in the Application, Fast in SSMS?。
-
您可以使用您的查询创建一个存储过程并从 EF 调用它,它会快得多。
-
更好地显示 LINQ 查询。
-
或者问题出在连接...或者您的 linq 查询在 sql 中做不到...我们需要您的 linq 查询,就像 Svyatoslav 说的...
-
通常的疑点:延迟加载(n+1 加载)。再次:显示 LINQ 查询 + 类模型。现在不可能再说什么更有帮助的了。
标签: c# sql-server entity-framework-core