使用LINQ高效分页大数据集

时间:2015-02-11 01:13:23

标签: c# .net linq

在研究在C#中实现分页的最佳方法时(使用LINQ),大多数建议都是这样的:

// Execute the query
var query = db.Entity.Where(e => e.Something == something);

// Get the total num records
var total = query.Count();

// Page the results
var paged = query.Skip((pageNum - 1) * pageSize).Take(pageSize);

这似乎是通常建议的策略(简化)。

对我来说,我的分页主要目的是提高效率。如果我的表包含120万条记录,其中Something ==某些东西,我不想同时检索所有这些记录。相反,我想分页数据,抓取尽可能少的记录。但是用这种方法,似乎这是一个有争议的问题。

如果我理解正确,第一个语句仍然会检索120万条记录,然后会根据需要对其进行分页。

以这种方式进行分页是否真的能提高性能?如果每次都要检索120万条记录,那么重点是什么(除了显而易见的UI好处)?

我误解了这个吗?任何.NET专家都可以给我一个关于LINQ,分页和性能的课程(处理大型数据集时)?

3 个答案:

答案 0 :(得分:6)

第一个语句不执行实际的SQL查询,它只构建您要运行的查询的一部分。

当你致电query.Count()时,第一个将被执行

SELECT COUNT(*) FROM Table WHERE Something = something

query.Skip().Take()上也不会执行查询,只有当您尝试枚举结果时(在paged上执行foreach或在其上调用.ToList())它将执行适当的SQL语句,仅检索页面的行(使用ROW_NUMBER)。

如果在SQL事件探查器中观察到这一点,您将看到正好执行了两个查询,并且它不会尝试检索完整的表。


使用调试器时要小心,因为如果您在第一个语句之后执行操作并尝试查看将执行SQL查询的query的内容。也许这是你误解的根源。

答案 1 :(得分:3)

// Execute the query
var query = db.Entity.Where(e => e.Something == something);

对于您的信息,在第一个语句之后没有任何内容被称为

// Get the total num records
var total = query.Count();

此计数查询将被转换为SQL,并且它将调用数据库。 此调用不会获取所有记录,因为生成的SQL是这样的:

SELECT COUNT(*) FROM Entity where Something LIKE 'something'

对于上一个查询,它既没有获得所有记录。查询将被转换为SQL,并且分页将在数据库中运行。

也许您会发现这个问题很有用:efficient way to implement paging

答案 2 :(得分:2)

我相信实体框架可能会根据linq语句使用适当的条件构造SQL查询。 (例如使用ROWNUMBER()OVER ...)。

然而,我可能错了。我运行SQL事件探查器,看看生成的查询是什么样的。