【问题标题】:Optimizing a LINQ to SQL query优化 LINQ to SQL 查询
【发布时间】:2008-09-08 17:05:22
【问题描述】:

我的查询如下所示:

public IList<Post> FetchLatestOrders(int pageIndex, int recordCount)
{
    DatabaseDataContext db = new DatabaseDataContext();
    return (from o in db.Orders
            orderby o.CreatedDate descending
            select o)
            .Skip(pageIndex * recordCount)
            .Take(recordCount)
            .ToList();
}

我需要打印订单的信息和创建它的用户:

foreach (var o in FetchLatestOrders(0, 10))
{
    Console.WriteLine("{0} {1}", o.Code, o.Customer.Name);
}

这会生成一个 SQL 查询来带来订单,并为每个订单生成一个查询来带来客户。是否可以优化查询,以便在一个 SQL 查询中带来订单和客户?

谢谢

UDPATE:根据 Sirrocco 的建议,我更改了这样的查询并且它有效。只生成一个选择查询:

public IList<Post> FetchLatestOrders(int pageIndex, int recordCount)
{
    var options = new DataLoadOptions();
    options.LoadWith<Post>(o => o.Customer);
    using (var db = new DatabaseDataContext())
    {
        db.LoadOptions = options;
        return (from o in db.Orders
                orderby o.CreatedDate descending
                select o)
                .Skip(pageIndex * recordCount)
                .Take(recordCount)
                .ToList();
    }
}

谢谢sirrocco。

【问题讨论】:

    标签: linq linq-to-sql optimization


    【解决方案1】:

    您可以做的其他事情是 EagerLoading。在 Linq2SQL 中,您可以使用 LoadOptions :More on LoadOptions 关于 L2S 的一个非常奇怪的事情是,您只能在第一个查询发送到数据库之前设置 LoadOptions。

    【讨论】:

    【解决方案2】:

    您可能想研究使用已编译的查询

    看看http://www.3devs.com/?p=3

    【讨论】:

      【解决方案3】:

      给定一个 LINQ 语句,例如:

      context.Cars
        .OrderBy(x => x.Id)
        .Skip(50000)
        .Take(1000)
        .ToList();
      

      这大致翻译成:

      select * from [Cars] order by [Cars].[Id] asc offset 50000 rows fetch next 1000 rows
      

      因为 offset 和 fetch 是 order by 的扩展,所以它们直到 select-portion 运行后才会执行(google)。这意味着在获取获取结果之前,会在整个数据集([Cars])上执行包含大量连接语句的昂贵选择。

      优化语句 所需要的只是获取 OrderBy、Skip 和 Take 语句并将它们放入 Where 子句中:

      context.Cars
        .Where(x => context.Cars.OrderBy(y => y.Id).Select(y => y.Id).Skip(50000).Take(1000).Contains(x.Id))
        .ToList();
      

      这大致翻译成:

      exec sp_executesql N'
      select * from [Cars]
      where exists
        (select 1 from
          (select [Cars].[Id] from [Cars] order by [Cars].[Id] asc offset @p__linq__0 rows fetch next @p__linq__1 rows only
          ) as [Limit1]
          where [Limit1].[Id] = [Cars].[Id]
        )
      order by [Cars].[Id] asc',N'@p__linq__0 int,@p__linq__1 int',@p__linq__0=50000,@p__linq__1=1000
      

      所以现在,外部选择语句仅在基于 where 存在子句的过滤数据集上执行!

      同样,您的里程可能会因进行更改节省的查询时间而异。一般的经验法则是,您的选择语句越复杂,您想要进入的数据集越深入,这种优化就越有帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-13
        • 1970-01-01
        • 2012-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多