当要跳过的数字很大时,实体Framerowk Skip / Take非常慢

时间:2015-12-30 14:56:26

标签: sql performance entity-framework linq

所以,代码非常简单:

var result = dbContext.Skip(x).Take(y).ToList();

当x很大(~1.000.000)时,查询非常慢。 y很小 - 10,20。

这个的SQL代码是:(来自sql profiler)

SELECT ...
FROM ...
ORDER BY ...
OFFSET x ROWS FETCH NEXT y ROWS ONLY

问题是,是否有人知道如何加快这种分页? 感谢。

4 个答案:

答案 0 :(得分:4)

我认为OFFSET .. FETCH在浏览大数据中的第一页(在大多数应用程序中经常发生)时非常有用,并且在查询高阶页时遇到性能问题大数据。

检查此article,详细了解OFFSET .. FETCH的效果和替代方案。

尝试在应用分页之前对数据应用尽可能多的过滤器,以便针对较小的数据量运行分页。很难想象用户不希望导航到1M行。

答案 1 :(得分:4)

导航虽然数据库中的一百万条记录与其他方式相比总是很慢,但数据库必须跳过"跳过"一百万条记录,它通过在内存中创建结果然后丢弃第一百万行来实现这一点。

您是否考虑过非sql替代(solr,lucene等),至少先获取行的ID然后在()查询中使用where id?

或者你可以使用主表的搜索表(煮熟的表),只有最小的数据和ID,所以你可以跳过它并获取id并用那些查询大表。

答案 2 :(得分:4)

你是对的,Skip()。在SQL服务器上Take()方法很慢。当我注意到我使用了另一种方法并且效果很好时。而不是使用Linq Skip()。Take() - 它编写您显示的代码 - ,我明确地将SQL编写为:

name: { type: Types.Text, required: true, index: true, refPath: 'project' }

这个工作得很快(考虑到我有按列排序的索引)。

答案 3 :(得分:2)

你的表上可能缺少一些索引(或者你可能有太多索引),导致SQL排序/过滤无法有效地跳过那么多行(或者索引太多,导致失败)为工作选择一个好的指数。)

尝试直接测试SQL查询:

  • 检查其实际执行计划,
  • 检查是否缺少索引提示(可能需要将查询重写为非动态sql查询,如果ef已发出一些动态查询代码),
  • 检查临时数据库溢出的排序,
  • ...

因此,简而言之,检查问题是否真的是实体框架问题或“纯”SQL问题。

附注:只有在为SQL2012方言配置时,EF才会发出offset/fetch分页查询。对于以前的方言,它使用row_number()代替。