【问题标题】:Iteration over a linq to sql query is very slow对 linq to sql 查询的迭代非常慢
【发布时间】:2010-06-16 10:17:16
【问题描述】:

我的数据库中有一个视图 AdvertView,这个视图是一些表(广告、客户、属性)之间的简单连接。然后我有一个简单的 linq 查询来获取客户的所有广告:

public IEnumerable<AdvertView> GetAdvertForCustomerID(int customerID)
{
    var advertList = 
        from advert in _dbContext.AdvertViews
        where advert.Customer_ID.Equals(customerID)
        select advert;
    return advertList;
}

然后我希望将其映射到我的 MVC 应用程序的 modelItems:

public List<AdvertModelItem> GetAdvertsByCustomer(int customerId)
{
    List<AdvertModelItem> lstAdverts = new List<AdvertModelItem>();
    List<AdvertView> adViews = _dataHandler.GetAdvertForCustomerID(customerId).ToList();
    foreach(AdvertView adView in adViews)
    {
        lstAdverts.Add(_advertMapper.MapToModelClass(adView));
    }
    return lstAdverts;
}

我原以为 SQL 会出现一些性能问题,但问题似乎出在 .ToList() 函数上。我正在使用 ANTS 性能分析器,它报告该函数的总运行时间为 1.400 毫秒,其中 850 个与 ToList() 一起使用。所以我的问题是,为什么 tolist 函数在这里需要这么长时间?

【问题讨论】:

    标签: linq-to-sql c#-4.0


    【解决方案1】:

    GetAdvertForCustomerID 不返回结果,它返回一个查询。

    ToList 枚举查询。结果在那个时候是水合的。数据库之旅发生在 ToList 调用中。

    您应该获取生成的 sql(通过使用 SqlProfiler 或 DataContext.Log 属性),并将其带到查询分析器以检查执行计划和 IO(SET STATISTICS IO ON)。

    【讨论】:

    • 大卫就在这里。 IMO 你应该隐式返回 IQueryables。返回 List&lt;T&gt;T[] 或使用 IQueryable&lt;T&gt; 作为方法定义的返回类型。这使得将要发生的事情非常明确。
    • 我对方法的返回类型没有任何意见。一个基本的 linq 事实是查询在枚举时执行。 ToList 枚举其源。这种知识在 linq 世界中与知道代码行按顺序执行一样重要。
    • 我之前的评论中的错字。它应该是“你不应该隐式返回 IQueryables”。
    • 但是,您的方法的用户可能不会期望两次迭代集合会导致对数据库的两次调用。
    • 如果给我一个 IQueryable 并且不知道生成它的原因,我肯定会将其视为昂贵的仅迭代一次源。
    【解决方案2】:

    .ToList 将执行查询,因此包括到数据库的整个往返过程、获取数据以及为返回的每条记录具体化实体对象... ...您很可能大部分时间都在 db -side,因此请仔细查看您的视图的执行计划。

    【讨论】:

    • DB端执行时间(根据SqlServer profiler = 0,有139个IO ops。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多