我正在使用EntityFramework 6,我将Linq查询从Asp.NET服务器发送到azure sql数据库。
我需要检索满足特定条件的最新20行
以下是我的查询的粗略示例
using (PostHubDbContext postHubDbContext = new PostHubDbContext())
{
DbGeography location = DbGeography.FromText(string.Format("POINT({1} {0})", latitude, longitude));
IQueryable<Post> postQueryable =
from postDbEntry in postHubDbContext.PostDbEntries
orderby postDbEntry.Id descending
where postDbEntry.OriginDbGeography.Distance(location) < (DistanceConstant)
select new Post(postDbEntry);
postQueryable = postQueryable.Take(20);
IOrderedQueryable<Post> postOrderedQueryable = postQueryable.OrderBy(Post => Post.DatePosted);
return postOrderedQueryable.ToList();
}
问题是,如果我的数据库中有十亿行,该怎么办?该查询是否会粗暴地选择数百万行符合条件然后获得20个行?或者它是否聪明并意识到我只需要20行,因此它只会选择20行?
基本上,如何使用具有十亿行的数据库有效地使此查询有效?
答案 0 :(得分:2)
根据http://msdn.microsoft.com/en-us/library/bb882641.aspx Take()函数延迟了流执行以及select语句。这意味着它应该等同于SQL中的TOP 20
,SQL将只从数据库中获取20行。
此链接:http://msdn.microsoft.com/en-us/library/bb399342(v=vs.110).aspx表明Take在Linq-to-SQL中有直接翻译。
因此,您可以在数据库中进行唯一的性能。与@usr建议您可以使用索引来提高性能。另外,按排序顺序存储表有很大帮助(按ID排序可能就是这种情况)。
答案 1 :(得分:1)
为什么不尝试一下? :)您可以检查sql并查看它生成的内容,然后查看该sql的执行计划,看看它是否扫描整个表
查看此问题以获取更多详细信息 How do I view the SQL generated by the Entity Framework?
答案 2 :(得分:1)
这很难变得非常快。您希望索引在Id
上为您提供排序顺序,但您需要一个不同的(空间)索引来为您提供有效的过滤。无法创建有效实现两个目标的索引。
假设两个索引都存在:
如果过滤器非常有选择性希望SQL Server能够选择&#34;这个过滤器为真的所有行,然后对它们进行排序,然后给你排在前20位。想象一下只有21行通过过滤器 - 那么这个策略显然非常有效。
如果过滤器根本没有选择性 SQL Server宁愿遍历由Id排序的表,请测试它所经过的每一行并输出前20行。想象一下过滤器适用于所有行 - 然后SQL Server可以输出它看到的前20行。很快。
因此,对于100%或0%选择性,查询将很快。在两者之间存在令人讨厌的混合物。如果你有这个问题需要进一步思考。您可能需要的不仅仅是一个聪明的索引策略。您需要更改应用。
顺便说一下,我们不需要DatePosted
上的索引。只有在将设置限制为20行后才能按DatePosted
排序。我们不需要索引来排序20行。