SQL Linq .Take()来自HUGE数据库的最后20行,性能方面

时间:2014-05-31 21:37:03

标签: c# performance entity-framework geospatial

我正在使用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行?

基本上,如何使用具有十亿行的数据库有效地使此查询有效?

3 个答案:

答案 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行。