我使用EF5和通用存储库、工作单元模式对SQL Server2008数据库进行了以下LINQ查询
var countriesArr = GetIdsFromDelimStr(countries);
var competitionsArr = GetIdsFromDelimStr(competitions);
var filterTeamName = string.Empty;
if (teamName != null)
{
filterTeamName = teamName.ToUpper();
}
using (var unitOfWork = new FootballUnitOfWork(ConnFooty))
{
// give us our selection of teams
var teams =
(from team in
unitOfWork.TeamRepository.Find()
where ((string.IsNullOrEmpty(filterTeamName) || team.Name.ToUpper().Contains(filterTeamName)) &&
(countriesArr.Contains(team.Venue.Country.Id) || countriesArr.Count() == 0))
select new
{
tId = team.Id
}).Distinct();
// give us our selection of contests
var conts = (
from cont in
unitOfWork.ContestRepository.Find(
c =>
((c.ContestType == ContestType.League && competitionsArr.Count() == 0) ||
(competitionsArr.Contains(c.Competition.Id) && competitionsArr.Count() == 0)))
select new
{
contId = cont.Id
}
).Distinct();
// get selection of home teams based on contest
var homecomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
where
teams.Any(t => t.tId == fixt.HomeTeam.Id) &&
conts.Any(c => c.contId == fixt.Contest.Id)
select new
{
teamId = fixt.HomeTeam.Id,
teamName = fixt.HomeTeam.Name,
countryId = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Id : 0,
countryName = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Name : string.Empty,
compId = fixt.Contest.Competition.Id,
compDesc = fixt.Contest.Competition.Description
}).Distinct();
// get selection of away teams based on contest
var awaycomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
where
teams.Any(t => t.tId == fixt.AwayTeam.Id) &&
conts.Any(c => c.contId == fixt.Contest.Id)
select new
{
teamId = fixt.AwayTeam.Id,
teamName = fixt.AwayTeam.Name,
countryId = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Id : 0,
countryName = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Name : string.Empty,
compId = fixt.Contest.Competition.Id,
compDesc = fixt.Contest.Competition.Description
}).Distinct();
// ensure that we return the max competition based on id for home teams
var homemax = (from t in homecomps
group t by t.teamId
into grp
let maxcomp = grp.Max(g => g.compId)
from g in grp
where g.compId == maxcomp
select g).Distinct();
// ensure that we return the max competition based on id for away teams
var awaymax = (from t in awaycomps
group t by t.teamId
into grp
let maxcomp = grp.Max(g => g.compId)
from g in grp
where g.compId == maxcomp
select g).Distinct();
var filteredteams = homemax.Union(awaymax).OrderBy(t => t.teamName).AsQueryable();
正如您所看到的,我们希望返回以下格式,该格式被传递给一个WebAPI,因此我们将结果转换为我们可以在UI中关联的类型。
本质上,我们试图做的是让主客场球队从一场比赛中脱颖而出,这些比赛有一场与比赛相关的比赛。然后,我们从分组中获得最高的竞赛id,然后将该id与该团队一起返回。国家是与基于场地id的球队相关的,当我最初这样做的时候,我在弄清楚如何在linq中做或加入时遇到了问题,这就是为什么我把它分成了主队和客队,然后根据竞争将他们分组,然后将他们联合在一起。
当前表格大小的想法是固定有7840行,团队有8581行,比赛有337行,比赛有96行。可能快速增加的表是固定表,因为这与足球相关。
我们希望最终得到的输出是
团队Id,团队名称,国家/地区Id,国家/地区名称,比赛Id,比赛名称
如果不使用过滤,这个查询平均需要大约5秒,只是想知道是否有人有任何想法/建议如何让它更快。
提前感谢马克
发布于 2013-06-09 06:59:22
我不能判断它是否会加快速度,但您的homemax
和awaymax
查询可能是
var homemax = from t in homecomps
group t by t.teamId into grp
select grp.OrderByDescending(x => x.compId).FirstOrDefault();
var awaymax = from t in awaycomps
group t by t.teamId into grp
select grp.OrderByDescending(x => x.compId).FirstOrDefault();
此外,当您正在编写一个非常大的查询时,如果您将它分割成几个较小的查询来获取中间结果,它可能会表现得更好。有时,与数据库引擎找不到好的执行计划的一个非常大的查询相比,对数据库的多几次往返执行要好得多。
另一件事是所有这些Distinct()
,你总是需要它们吗?我认为你可以不这样做,因为你总是从一个表中获取数据,而不是连接子集合。移除它们可能会节省一大笔钱。
另一个优化可能是删除ToUpper
。比较是由SQL中的数据库引擎完成的,数据库很可能具有不区分大小写的排序规则。如果是这样的话,即使你希望比较是大小写敏感的,它也不会区分大小写!像Name.ToUpper
这样的结构取消了对Name
的任何索引的使用(它不是sargable)。
https://stackoverflow.com/questions/16999839
复制相似问题