LINQ Skip()问题

Ahm*_*tun 5 c# sql linq

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

 int itemToSkip = 100;
 int itemToTake = 1000;

 var itemList = db.MYTABLEs.Skip(itemToSkip).Take(itemToTake).ToList();
Run Code Online (Sandbox Code Playgroud)

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

Ste*_*ung 8

不确定您提供的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的基本查询生成的查询复杂得多.这种复杂性可能导致性能下降甚至超时.

换句话说,文档说"不要这样做".

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

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

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

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