LINQ Skip()问题

下面的C#语句会阻止进程,如果itemToSkip大于0,则无法检索数据。

int itemToSkip = 100; int itemToTake = 1000; var itemList = db.MYTABLEs.Skip(itemToSkip).Take(itemToTake).ToList(); 

我该如何解决? 问题是什么?

不确定您提供的db.MYTABLEs提供商。 除非我们知道db.MYTABLEs的行为方式,否则无法回答您的问题。

在正常的LINQ中,跳过不只是向前跳; 它必须迭代数据量才能跳过。 因此,对于14gb数据表,它将迭代第一个“跳过”数量的记录。 如果此迭代很慢,则不会通过跳过来保存任何CPU /时间。

对于某些提供者,例如SQL源,可以使用游标实现跳过,这可能再次很慢。 如果是SQL Server,则可以使用可能更快的关键字对其进行优化。

如果它是LINQ-to-SQL,它会使用“NOT EXISTS”子句将查询转换为SQL,这将非常慢,因为如果NOT EXISTS子句没有命中索引,它必须遍历整个表。 请参阅以下内容( 链接 ):

LINQ to SQL通过使用带有SQL NOT EXISTS子句的子查询来转换Skip。 此翻译具有以下限制:

  • 参数必须是一组。 即使订购,也不支持多字节。

  • 生成的查询可能比为应用Skip的基本查询生成的查询复杂得多。 这种复杂性可能导致性能下降甚至超时。

换句话说,文档说“不要这样做”。

只有具有随机访问function的提供程序(例如内存数组)才会快速跳过,因为提供程序可以直接跳转。

最糟糕的情况是,如果您在提供程序上运行,如果您使用Skip / Take,则会自动对整个数据集进行排序。 如果你有14GB的数据,那么这种情况会非常慢。

您需要进行更多实验,以查看您的程序是否挂起,或者只是占用所有尝试迭代的cpu。

如果您只是想将数据划分为可管理的块,则可能不应该使用skip / take,它每次都会重新查询数据源。

Skip通常坚持要有明确的排序顺序。 尝试

 var itemList = db.MYTABLEs.OrderBy(r => r.Id).Skip(itemToSkip) 

或类似的。

我假设您的DBMS不支持直接跳过,因此可能会请求所有数据,具体取决于提供商。

有这么大的表可能只需要很长时间才能返回,并且由于缺少索引需要花费很长时间,你需要进行一些分析才能看到底层查询,你只能通过查看来诊断问题LINQ代码