【问题标题】:Handling large SQL queries with LINQ使用 LINQ 处理大型 SQL 查询
【发布时间】:2013-03-06 23:45:22
【问题描述】:

我正在尝试通过实体数据模型从包含大约 2000 万个条目的 MS SQL 数据库中的表中获取每条记录。我最初的想法是按块检索数据,如下所示:

public IEnumerable<IEnumerable<device>> GetDevicesInChunks(int chunkSize)
{
    using (var db = new AccountsEntities())
    {
        for (int i = 0; i < db.devices.Count(); i += chunkSize)
        {
            yield return db.devices.Skip(i).Take(chunkSize);
        }
    }
}

但是,从我使用上述方法时抛出的异常来看,我似乎必须在调用Skip 之前调用OrderBy

The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 
'OrderBy' must be called before the method 'Skip'.

我确信在我检索到的每个记录子集上调用 OrderBy 会很昂贵,因为这些设备没有特定的顺序 - 我觉得我在这里走错了路。

通过 LINQ 处理大型 SQL 查询的最佳方法是什么?

【问题讨论】:

  • 您不能使用Where 并通过主键而不是Skip 进行过滤吗?或者只是OrderBy主键?
  • 有什么特别的原因为什么你必须分块做这个吗?
  • @Tory 我认为一次加载 2000 万个实体就足够了..
  • 是什么样的数据?为什么需要全部加载?
  • OrderBy 聚集索引,如果表上存在;如果没有,OrderBy 主键...如果您必须 OrderBy。似乎很奇怪,它是必需的。

标签: c# .net sql-server linq entity-framework


【解决方案1】:

发生错误是因为方法 Skip 需要在 OrderBy 之后运行。如果没有 OrderBy,您将无法运行 Skip。方法Skip需要知道第一个取什么,如果放第一个需要知道select的顺序来知道第一个是从头到尾还是从尾到头的那个数字。

您可以阅读更多here

所以,您的代码如下所示:

public IEnumerable<IEnumerable<device>> GetDevicesInChunks(int chunkSize)
{
    using (var db = new AccountsEntities())
    {
        for (int i = 0; i < db.devices.Count(); i += chunkSize)
        {
            yield return db.devices.OrderByDescending(y => y).Skip(i).Take(chunkSize);
        }
    }
}

如果您认为这是一个繁重的查询,请记住 Entity Framework 可以对查询和数据进行缓存。如果你不喜欢那个方法的 sql 你可以run the query manually.

个人经验: 我将它与具有 2 bi 行的数据库一起使用,并且......它并不慢。但我的表中有索引,我总是使用缓存。

更多: 如果您愿意,可以使用程序。查看更多here

【讨论】:

  • 非常全面的答案,感谢所有信息和解释!为了确保我理解正确,OrderByDescending 表达式应该是 y => y.id 而不是 y => y,对吧?
【解决方案2】:

您可能不必执行OrderBy - 您可能只需要在执行SkipTake 之前填充列表。我认为您可以使用.Count() 来填充查询,之后您可以使用SkipTake

【讨论】:

  • 这将非常繁重,如您所说使用 Count 或 ToList 将填充查询,但将检索 2000 万条记录。
  • 是的......但它不会将整个集合推出服务器只是为了进行计数 - 它会在 MSSQL 中填充它。
猜你喜欢
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多