我有一个场景,它导致了非常长时间运行的进程,并怀疑这是我们使用LINQ。
背景:项目使用LINQ和Repository模式向我们的逻辑层公开数据。这就是它的现状,也不会改变。
问题:出现了一个特定的场景,需要从输入和其他表中选择相交数据。为了优化这一点,我首先查询DB中的ID数组,我打算使用这个数组来获取相交数据。我还可以在LINQ表达式中使用另一个整数数组。然后构建一个表达式,以便使用LINQ和contains方法从所讨论的表中选择数据。这需要很长时间才能执行。快一分钟了。
为了解决这个问题,我尝试了几种LINQ技术,它们几乎都需要同时使用。为了便于了解,下面是我的一些方法的示例。
// FYI: tableTotalsIds contains 14,856 IDs as an example, built from a repository call
var tableTotalsIds = tableTotals.Select(s => s.Id).ToArray();
int[] ages = {25, 26, 27};
Expression<Func<TotalAgeCounts, bool>> ageFilter =
af => af.TableTotalsId != null &&
tableTotalsIds.Contains(af.TableTotalsId.Value) &&
ages.Contains(af.Age);
var directStartTime = DateTime.Now;
var directFetch = _ctx.TotalAgeCounts.Where(ageFilter).ToList();
var directBenchMark = DateTime.Now.Subtract(directStartTime).TotalSeconds;
var repositoryStartTime = DateTime.Now;
var repositoryFetch = _totalAgeCountsRepository
.SelectAll(new Specification<TotalAgeCounts>(ageFilter));
var repositoryBenchMark = DateTime.Now.Subtract(repositoryStartTime).TotalSeconds;在所有情况下,查询时间大约为1分钟。让我吃惊的是,在.Contains()方法中使用了大量的LINQ,但我不知道其他实现这一目标的LINQ方法。
在LINQ中是否有一种更优化的方法来做到这一点?
目前,我正在考虑将这个查询作为一个简单的连接返回到DB中,并在这里跳过LINQ瓶颈。但是,首先,我将尝试将未过滤的数据拖到内存中,然后使用LINQ将数据连接在一起,看看效率如何。
我对其他人如何克服类似的瓶颈而不重写应用程序的体系结构感兴趣。
溶液
正如评论者所指出的,LINQ优化并没有因为我的.ToArray()而发生。问题更加严重,因为我正在使用我们的存储库实现来构建tableTotalsIds,它已经将结果转换为一个IList,从而失去了更多的LINQ/SQL优化。简单地说,不使用我们的存储库实现来构建tableTotalsIds和直接查询dataContext,只留下IQueryable修复问题的结果。
发布于 2012-05-09 12:42:38
实际上,您正在调用ToArray,这会导致筛选记录被从db中提取出来,而只是作为查询的一部分被再次注入。这使得查询优化器无法很好地利用它已经具备了所需的事实。正如您在逗号中所指出的,删除Tolist/toarray会有所帮助。
至于存储库模式,您没有理由不能使用它。您只是不需要为每个类建立一个单独的存储库;只需要对那些重要的根对象进行查询。
在本例中,您的助手表信息可以在同一个查询中汇总;存储库模式不要求您为它创建一个单独的存储库。
https://stackoverflow.com/questions/10515568
复制相似问题