C#的效率查找1000多条记录

时间:2014-01-09 15:56:24

标签: c# performance entity-framework

我试图基本上看看实体是否存在于本地上下文中并相应地对它们进行排序。这个功能似乎比我们尝试过的其他1000个项目在50秒内运行的速度要快,但我想知道是否有一些我可以做的事情来提高效率。我认为这里的发现显着减慢了它的速度,因为一个超过1000的简单foreach迭代需要几毫秒,基准测试显示瓶颈缩颈。任何想法都会有所帮助。谢谢。

示例代码:

                foreach(var entity in entities) {
                    var localItem = db.Set<T>().Find(Key);
                    if(localItem != null)
                    {
                       list1.Add(entity);
                    }
                    else 
                    {
                        list2.Add(entity);
                    }
                }

4 个答案:

答案 0 :(得分:3)

如果这是一个数据库(来自我收集的评论,那就是......)

最好少做一些查询。

list1.AddRange(db.Set<T>().Where(x => x.Key == Key));
list2.AddRange(db.Set<T>().Where(x => x.Key != Key));

这将是2个查询而不是1000 +。

还要注意这样一个事实:通过将每一个添加到List<T>,您将保留2个大型数组。因此,如果1000+变成10000000,那么你将会遇到有趣的内存问题。

请在我的博客上查看此帖子以获取更多信息:http://www.artisansoftware.blogspot.com/2014/01/synopsis-creating-large-collection-by.html

答案 1 :(得分:0)

如果我理解正确,数据库似乎是瓶颈?如果您希望(有效地)从数据库关系中选择数据,其属性x应与== - 条件匹配,则应考虑为该属性创建secondary access path(索引结构) 。根据您的数据库系统和表中的分布,这可能是哈希索引(特别适用于==)或B + -tree(allrounder)或系统为您提供的任何内容。

然而,这只适用于......

  • 您不仅可以获得一次完整的数据集,而且必须在您的应用程序中使用它。
  • 为关系添加(另一个)索引并不是不可能的(或者例如,单个需要它不值得)。
  • 添加索引无效 - 例如,如果您要查询的属性的唯一值很少。

答案 2 :(得分:0)

我发现你的答案非常有帮助,但最终我是如何解决问题的。好像.Find是瓶颈。

                 var tableDictionary = db.Set<T>().ToDictionary(x => x.KeyValue, x => x);

                foreach(var entity in entities) {
                    if (tableDictionary.ContainsKey(entity.yKeyValue))
                    {
                        list1.Add(entity);
                    }
                    else
                    {
                        list2.Add(entity);
                    }
                }

这在大约十分之一秒的时间内以900多行的速度运行,这对于我们的目的而言足够有效。

答案 3 :(得分:0)

您可以只执行一个查询,获取所有数据(因为您最终需要来自数据库的所有数据)而不是查询每个项目的数据库,然后您可以将其分组到内存中,这可以完成(在这种情况下)与数据库中一样有效。通过创建关键是否相等的查找,我们可以轻松获得两组:

var lookup = db.Set<T>().ToLookup(item => item.Key == Key);

var list1 = lookup[true].ToList();
var list2 = lookup[false].ToList();

(如果列表中包含之前应包含的值,则可以使用AddRange。)