在我们的数据库中,我们有一个包含超过100000个条目的表,但大多数时候我们只需要它的一部分。我们通过一个非常简单的查询来做到这一点。
items.AddRange(from i in this
where i.ResultID == resultID && i.AgentID == parentAgentID
orderby i.ChangeDate descending
select i);
在此查询之后,我们得到一个包含最多500个项目的列表。但即使从这个结果我们只需要最新的和以下的项目。我的同事用这个很简单:
items[0];
items[1];
正常工作,因为查询结果已按日期排序。但总体表现非常糟糕。甚至需要几秒钟。
我的想法是在查询结束时添加.Take(2)但我的同事说这没有任何区别。
items.AddRange((from i in resultlist
where i.ResultID == resultID && i.AgentID == parentAgentID
orderby i.ChangeDate descending
select i).Take(2));
我们还没有尝试过,我们仍在寻找其他方法来加快速度。但数据库编程不是我们强有力的一面,任何建议都会很棒。
也许我们甚至可以对数据库本身进行一些调整?我们使用SQL Compact Database。
答案 0 :(得分:2)
如果优化器相当聪明,并且特别是如果将ChangeDate列编入索引,那么使用Take(2)
确实会有所作为。 (我不知道SQL Compact版本有多少优化,但我仍然希望限制结果有用。)
但是,你不应该相信我或其他任何人这么说。查看每种情况下生成的查询,并针对SQL事件探查器运行它。了解执行计划是什么。使用各种样品测量性能。测量,测量,测量。
答案 1 :(得分:1)
您可能遇到的问题是数据被下拉到您的计算机,然后您正在执行Take(2)。可能花费最多时间的部分是将所有数据提取到您的应用程序。如果您希望SQL Server执行此操作,请确保在完成查询语句之前不访问任何结果集记录的值。
其次,LINQ对于排序和应用程序内存中大量数据的子句的处理速度并不快。有时在LINQ中编写要容易得多,但在数据库中执行尽可能多的排序和where子句总是更好,而不是在内存对象集中进行操作。
如果您真的关心此方案中的性能,请不要使用LINQ。只需制作一个循环。
http://ox.no/posts/linq-vs-loop-a-performance-test
我喜欢使用LINQ-To-SQL和LINQ,但它并不总是适合这项工作的工具。如果您有大量数据并且性能至关重要,那么您不希望在内存排序和where语句中使用LINQ。
答案 2 :(得分:0)
添加.Take(2)会产生很大的不同。如果你只需要两件物品,那么你一定要使用它,这肯定会给你带来性能差异。
添加它并查看从中生成的SQL。生成的SQL只能获得2条记录,这样可以节省SQL时间和对象实例化方面的时间。
答案 3 :(得分:0)
1 - 添加索引以涵盖您在查询中使用的字段
2 - 确保过于频繁地重复查询不能获得前2名
3 - 尝试编译LINQ查询