Linq查询花费太长时间来处理结果

时间:2020-03-25 13:10:13

标签: c# performance linq

我有3张桌子

  • ERPEntry
  • ERPEntryType
  • ERPApp

我正在尝试使用以下查询从这3个表中获取数据:。表ERPApp与其他2个表处于不同的上下文中,这就是我使用2个查询的原因

    Min     Max     Target
0   min1    max1    target1
1   min2    max2    target2

我得到了期望的结果,但是第二个查询要花将近4分钟的时间来处理并将结果返回到varibale erpResult ...有关如何解决此性能问题的任何帮助?

1 个答案:

答案 0 :(得分:0)

首先,答案:

var res = (from s in ERPDB.ERPEntries
join t in ERPDB.ERPEntryTypes
on s.EntryTypeID equals t.EntryTypeID
where s.UserIdAdded == "250176"
select new { s.EntryID, s.EntryTypeID, s.DateAdded, t.EntryTypeName, s.AppId })
.OrderByDescending(d => d.DateAdded).Take(10).ToArray();

/* Which immediately executes:

exec sp_executesql N'SELECT TOP (10) [t0].[EntryID], [t0].[EntryTypeID], 
[t0].[DateAdded], [t1].[EntryTypeName], [t0].[AppId]
FROM [dbo].[ERPEntry] AS [t0]
INNER JOIN [dbo].[ERPEntryType] AS [t1] ON [t0].[EntryTypeID] = [t1]. 
[EntryTypeID]
WHERE [t0].[UserIdAdded] = @p0
ORDER BY [t0].[DateAdded] DESC',N'@p0 varchar(8000)',@p0='250176'

*/

// Get the distinct AppID values in res
// Executes in memory
var distinctApps = (from r in res select r.AppId).Distinct();

// Query APPDB with the distinct values
var matchingApps = (from a in APPDB.ERPApps where distinctApps
.Contains(a.AppId) select new { a.AppId, a.ApplicationName }).ToArray();

/* Which immediately executes this efficient query:

exec sp_executesql N'SELECT [t0].[AppId], [t0].[ApplicationName]
FROM [dbo].[ERPApp] AS [t0]
WHERE [t0].[AppId] IN (@p0, @p1, @p2, @p3)',N'@p0 bigint,@p1 bigint,@p2 
bigint,@p3 bigint',@p0=101,@p1=123,@p2=125,@p3=129

*/ 
var erpResultWithAppNames = (from a in matchingApps
join b in res on a.AppId equals b.AppId
select new
{
EntryId = b.EntryID,
EntryType = b.EntryTypeName,
ERPApp = a.ApplicationName,
DateAdded = b.DateAdded
}).ToList();

附加说明:

正如注释中已经提到的那样,对.AsEnumerable()表上的APPDB.ERPApps的调用导致整个表作为对象加载到内存中。

事实:

  1. 您必须将25.000行加载到内存中(并将其转换为对象),

  2. 您不仅要加载25.000行。您正在加载25.000 x 173个单元,并创建25.000个对象,每个对象具有173个字段。

  3. 如果您可以仅加载所需的两个字段(AppId和ApplicationName),而不是全部173个字段(包含它们具有的任何数据),则性能会提高,但考虑到您要尝试的内容,效率仍然很低实现。

  4. 当前的性能问题部分是由于将整个表及其173个字段转移到服务器,部分原因是将所有这些行映射到对象,将字段映射到属性。每种方法的影响都可以进行进一步的研究。

Linq To SQL。用SqlProfiler检查时:

from a in APPDB.ERPApps.AsEnumerable() join b ...

// PROFILED QUERY:
SELECT [t0].[AppId], [t0].[ApplicationName], [t0].[Field1], [t0].[Field2],
[t0].[Field3], [t0].[Field4], [t0].[Field5], [t0].[Field6], [t0].[Field7],
[t0].[Field8], [t0].[Field9], ... ... ... ... [t0].[Field176], [t0].[Field173],
FROM [dbo].[ERPApp] AS [t0]

但是:

var erpResult = (from a in APPDB.ERPApps
select new { AppId = a.AppId, ApplicationName = a.ApplicationName }
).ToArray();

// PROFILED QUERY:

SELECT [t0].[AppId], [t0].[ApplicationName]
FROM [dbo].[ERPApp] AS [t0]