我有一个LINQ查询,我在优化时遇到问题,需要大约5.5秒才能运行。我正在使用一个名为StaffingResourceData的视图和一个名为StaffingForecasts的表。
每个StaffingResource都有一个ResourceId,一个Division和一个Type。 StaffingForecast有一个ResourceId,Project,Date(表示一周的星期一),Hours。 StaffingResource可以有0多个StaffingForecasts。
对于每个StaffingResource,我需要一份他们未来12周的总预测时间列表。这就是我现在所拥有的:
// Get list of dates
var dates = new List<DateTime>();
var start = Utilities.GetStartOfWeek(DateTime.Today);
for (var i = 0; i < 12; i++)
{
dates.Add(start.AddDays(i * 7));
}
var end = dates[11];
// Get resources
var resources = (from r in context.StaffingResourceDatas
where r.EmployeeId != null
&& !exclusionList.Contains(r.ResourceTitleId)
join f in context.StaffingForecasts.Where(x => x.Date >= start && x.Date <= end) on r.ResourceId equals f.ResourceId into g1
from f in g1.DefaultIfEmpty()
group new { f.Date, f.Hours } by r into g2
select new ChartResourceModel
{
ResourceId = g2.Key.ResourceId,
Division = g2.Key.ResourceDivision,
Type = g2.Key.ResourceType,
Dates = dates.Select(d => new ChartDateModel
{
Date = d,
Available = (g2.Where(f => f.Date == d).Any() ? g2.Where(f => f.Date == d).Sum(f => f.Hours) : 0) < 24
}).ToList()
})
.ToList();
关于如何加快速度的任何想法?
答案 0 :(得分:6)
避免使用Contains
。它严重降低了性能。 See this post
ToList()
是执行查询的命令。直到你调用ToList()
方法,linq查询才会启动,因为linq有一个名为延迟执行的功能。因此,如果您调用ToList()
,则可以使用Databaseof文件启动一些实际操作。
关闭更改跟踪和身份管理(例如,LINQ-to-SQL中的ObjectTrackingEnabled)
using (YourDataContext dataContext = new YourDataContext())
{
dataContext.ObjectTrackingEnabled = false;
//Your code
}
.AsNoTracking()
。 The extensive description can be seen here. 答案 1 :(得分:1)
在玩了一段时间之后,我能够将加载时间从5.5秒降低到1.5秒。以下是我提出的建议:
// Get resources
var resources = (from r in
(from r in context.StaffingResourceDatas
where r.EmployeeId != null
&& !exclusionList.Contains(r.ResourceTitleId)
join f in context.StaffingForecasts on r.ResourceId equals f.ResourceId
group f by r into g
select new
{
Resource = g.Key,
Forecasts = g.Where(f => f.Date >= start && f.Date <= end && f.StaffingPotentialProject == null).ToList()
}).ToList()
group r.Forecasts by r.Resource into g
select new ChartResourceModel
{
ResourceId = g.Key.ReportsToId,
Division = g.Key.ResourceDivision,
Type = g.Key.ResourceType,
Dates = dates.Select(d => new ChartDateModel
{
Date = d,
Available = (g.SelectMany(f => f.Where(x => x.Date == d)).Sum(x => x.Hours)) < 24
}).ToList()
}).ToList();
似乎最好的方法是获取所需的所有数据并调用.ToList()而不尝试做任何奇特的事情,然后对该数据执行任何额外的操作。
答案 2 :(得分:0)
首先,尽量避免使用&#34; .ToList()&#34;除非一切都已完成,因为当您触发&#34; .ToList()&#34;时,结果正在实现,如果有大量数据并且您想要执行更多查询操作,则不需要关于那些数据。
因此,尝试使用IQueryable属性,这样您至少可以更快地获取数据,然后对其进行一些操作。
当然,检查您要发送给SQL的查询/查询是什么。也许你正在搜索的列没有正确编入索引(!?),或者你没有表中的任何索引(?)。
答案 3 :(得分:0)
答案 4 :(得分:0)
我会把我的赌注放在一个简单的子查询上,“自然地”代表所需的信息,比如这个
var query =
from r in context.StaffingResourceDatas
where r.EmployeeId != null && !exclusionList.Contains(r.ResourceTitleId)
select new ChartResourceModel
{
ResourceId = r.ResourceId,
Division = r.ResourceDivision,
Type = r.ResourceType,
Dates = dates.Select(d => new ChartDateModel
{
Date = d,
Available = context.StaffingForecasts.Where(f =>
f.ResourceId == r.ResourceId && f.Date == d).Sum(f => f.Hours) < 24
}).ToList()
};
var sqlQuery = query.ToString();
var result = query.ToList();