我有以下代码可以正常工作,但我在性能方面遇到了一些问题。通过调试,我可以看到当代码到达下面的这一行时,需要10秒才能完成。
List<T> queryableListdResult = queryableInitialResult.ToList();
基本上,下面这段代码从数据库中的150000条记录中获取了大约15000篇文章。
有人可以建议一个更好的方法吗?谢谢!
我的代码:
public static IQueryable<T> CategoryFilter<T>(IQueryable<T> queryable, int categoryFilterCount, RenderingContext rc, bool CategoryOR, string categoriesforQuery) where T : AbstractResult
{
if (!string.IsNullOrEmpty(categoriesforQuery))
{
string[] categoriesDefined = categoriesforQuery.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
List<T> listInitialResult = new List<T>();
foreach (string TaxonomyID in categoriesDefined) //e.g. entertainment, business
{
string categoryToCompare = TaxonomyID.ToString().Replace("{", "").Replace("}", "");
queryable = queryable.Where(i => i.alltags.Contains(categoryToCompare));
List<T> queryableListdResult = queryable.ToList();
listInitialResult.AddRange(queryableListdResult);
}
if (CategoryOR)
{
return listInitialResult.AsQueryable();
}
else
{
List<T> queryableFinalResult = (listInitialResult.GroupBy(x => x._Group).Where(g => g.Count() >= categoryFilterCount)
.Select(g => g.FirstOrDefault())).ToList();
return queryableFinalResult.AsQueryable();
}
}
else
{
return queryable;
}
}
答案 0 :(得分:1)
除装载卡车装载的数据外。
在处理方面,有一些技巧可以最大化EF上下文。
例如Context.Configuration.AutoDetectChangesEnabled = false;
您的代码段建议每次迭代都可以执行toList()。 您可能希望以不同的方式获得
List<T> queryableListdResult = queryableInitialResult.ToList();
答案 1 :(得分:0)
试试这个。我拿了你的代码并将其并行化。
public static IQueryable<T> CategoryFilter<T>(IQueryable<T> queryable1, int categoryFilterCount, RenderingContext rc, bool CategoryOR, string categoriesforQuery) where T : AbstractResult
{
if (!string.IsNullOrEmpty(categoriesforQuery))
{
string[] categoriesDefined = categoriesforQuery.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
ConcurrentBag<T> listInitialResult = new ConcurrentBag<T>();
Parallel.ForEach(categoriesDefined, (TaxonomyID) =>
{
string categoryToCompare = TaxonomyID.ToString().Replace("{", "").Replace("}", "");
var queryable = queryable.Where(i => i.alltags.Contains(categoryToCompare));
List<T> queryableListdResult = queryable.ToList();
for (int i = 0; i < queryableListdResult.Count; i++)
{
listInitialResult.Add(queryableListdResult[i]);
}
});
if (CategoryOR)
{
return listInitialResult.AsQueryable();
}
else
{
List<T> queryableFinalResult = (listInitialResult.GroupBy(x => x._Group).Where(g => g.Count() >= categoryFilterCount)
.Select(g => g.FirstOrDefault())).ToList();
return queryableFinalResult.AsQueryable();
}
}
else
{
return queryable;
}
}
另外,我使用了一个并发包,我相信LockLess的事情。希望这有帮助!
答案 2 :(得分:0)
请考虑您要查询的数据量。假设每篇文章只有1kB的数据。你正在拉下15k实体,你仍然试图从数据库中获取15MB的数据。假设10Mb / s的链路在数据传输速率方面10秒就完全正确。
我建议您投射查询以避免提取不必要的数据或升级数据链接。
但是,如果您需要的是您的代码更具响应性,那么您实际上可以使用流IEnumerable<T>
。您只需使用DbSet<T>.AsStreaming()
方法。这将在IEnumerator.Next()
的每次调用中分摊数据传输的成本。但是我警告你,数据传输本身需要更长的时间,并且你将在传输的整个过程中保持一个datareader锁定。
真正更实际地阅读你的问题。你真正想要的是IQueryable.Concat
。有了这个,你可以在每个IQueryable上过滤你想要的一切,然后将它们连接在一起,最后.ToList()
。