使用Linq选择前100条记录

时间:2009-08-18 20:58:09

标签: c# linq

如何使用Linq返回前100条记录?

我有一张有4000万条记录的桌子。

此代码有效,但速度很慢,因为它会在filter之前返回所有值:

var values = (from e in dataContext.table_sample
              where e.x == 1
              select e)
             .Take(100);

有没有办法返回过滤?喜欢T-SQL TOP子句吗?

5 个答案:

答案 0 :(得分:28)

不,在过滤之前不会返回所有值。 Take(100)最终将成为发送的SQL的一部分 - 很可能使用TOP。

当然,当您指定orderby子句时,这样做会更有意义。

LINQ在到达查询表达式的末尾时不执行查询。只有当您调用聚合运算符(例如CountAny)或者您开始​​迭代结果时,它才会发送任何SQL。甚至调用Take实际上并不执行查询 - 例如,您可能希望在此之后对其进行更多过滤,这可能最终成为查询的一部分。

当您开始迭代结果时(通常使用foreach) - 当SQL实际发送到数据库时

(顺便说一下,我认为你的where条款有点不完整。如果你的真实代码出现问题,那么将代码视为接近现实可能的。)

答案 1 :(得分:2)

我认为你在进入前100名之前返回所有记录并不正确。我认为Linq决定执行查询时的SQL字符串(也称为Lazy Loading)和数据库服务器将优化它。

答案 2 :(得分:2)

您是否将标准SQL查询与linq查询进行了比较?哪一个更快,差异有多大?

我同意上述评论,你的linq查询通常是正确的,但是......

    你的'where'子句中的
  • 应该是x == 1而不是x = 1(比较而不是赋值)
  • 'select e'将返回您可能只需要其中一些列的所有列 - 使用select子句更精确(仅键入必需的列); 'select *'是一种资源的浪费
  • 确保您的数据库编入索引并尝试使用索引数据

无论如何,40milions记录数据库非常庞大 - 你是否一直需要所有数据?也许某种分区可以将它减少到最常用的记录。

答案 3 :(得分:2)

我同意Jon Skeet,但只是想补充一下:

  1. 生成的SQL 使用TOP来实现Take()。

  2. 如果您能够运行SQL-Profiler并在调试模式下逐步执行代码,您将能够确切地看到生成什么SQL以及何时执行它。如果你有时间做这件事,你将会了解到底下发生的事情。

  3. 还有一个DataContext.Log属性,您可以指定TextWriter来查看生成的SQL,例如:

    dbContext.Log = Console.Out;

  4. 另一种选择是试验LINQPad。 LINQPad允许您连接到您的数据源并轻松尝试不同的LINQ表达式。在结果面板中,您可以切换以查看生成LINQ表达式的SQL。

答案 4 :(得分:1)

我要走出困境,并猜测你的where子句中使用的列没有索引。如果是这种情况,那么当查询实现时,毫无疑问会进行表扫描,这就是它花费这么长时间的原因。