为什么LINQ to SQL比直接SQL查询表现更好?

时间:2008-10-21 05:05:27

标签: .net sql-server linq-to-sql

奇怪的性能结果,我有一个LINQ to SQL查询,它使用几个let语句来获取它看起来像这样的各种信息

    public IQueryable<SystemNews> GetSystemNews()
{
    using (var t = new TransactionScope(TransactionScopeOption.Required,
              new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
    {
        var results = from s in _datacontext.SystemNews
                      let member = GetMemberInfo(s.MemberID)
                      let determination = GetDetermination(s.DeterminationID.Value)
                      let daimoku = GetDaimoku(s.DaimokuID.Value)
                      let entry = GetEntry(s.EntryID.Value)
                      let encouragment = GetEncouragement(s.EncouragementID.Value)
                      select new SystemNews
                      {
                          NewsDate = s.NewsDate,
                          MemberID = s.MemberID,
                          PhotoID = s.PhotoID.Value,
                          DeterminationID = s.DeterminationID.Value,
                          DaimokuID = s.DaimokuID.Value,
                          EntryID = s.EntryID.Value,
                          EncouragementID = s.EncouragementID.Value,
                          Member = new LazyList<Members>(member),
                          Determination = new LazyList<Determinations>(determination),
                          Daimoku = new LazyList<MemberDaimoku>(daimoku),
                          Entry = new LazyList<MemberEntries>(entry),
                          Encouragement = new LazyList<MemberEncouragements>(encouragment),
                          IsDeterminationComplete = s.IsDeterminationComplete.Value
                      };
        return results;
    }
}

我在SQL视图中创建了相同的东西(基本上至少是在此获得的各种信息),并且LINQ to SQL在90毫秒内返回结果,其中视图返回相同的数据实际上更少的信息700毫秒。谁能解释一下呢?

4 个答案:

答案 0 :(得分:4)

一般来说,LINQ-to-SQL将“大致相同”,我同意缓存在这里可能是个问题。真的,你需要查看生成的SQL;最简单的方法是:

_datacontext.Log = Console.Out;

然后尝试直接在查询分析器中运行TSQL。 SPROC在优化访问,使用表变量等方面具有一些优势;但是,LINQ具有可组合性的优点 - 即您可以在单个查询中应用分页,排序,投影等。你可以推动使用SPROC做到这一点,但这是非常辛苦的工作。

但实际上,关键在于查看TSQL;可能是您没有加载所有数据,例如(延迟加载)。

答案 1 :(得分:1)

您是否使用SQL事件探查器检查LINQ生成的SQL与您用于比较的SQL之间的差异?

也许LINQ to SQL查询更好地优化了?

答案 2 :(得分:0)

您可能会看到缓存效果;这不是真的。

基准测试的一个原则是,您可以通过运行基准测试一次,将结果放入缓存,然后再次运行并报告惊人的结果,或者反过来来偏向您的基准测试......

答案 3 :(得分:0)

粗略地看一下,你的Linq to SQL查询似乎正在使用延迟加载。如果我是对的那么有意义的是,运行查询时不会实际运行查询的所有部分。这意味着如果将它与SQL View进行比较,该SQL View被设置为一次性地恢复所有这些结果,那肯定会更多的工作,因此需要额外的时间。

另外两点:

  1. 确保您正在计算实际的查询执行时间,而不是查询表达式的赋值。记住Linq查询是延迟的,因此当您从上面的方法返回查询时,它实际上是返回表达式而不是结果。通常,执行Linq查询的三种常用方法是运行ToArray或ToList扩展方法,或者简单地使用foreach迭代结果。

  2. 如果你实际上正在进行延迟加载并对查询的实际执行进行计时,并且最终在Linq to SQL中得到更好的结果,那可能是由于SQL View返回的广泛平坦结果的差异与使用Linq to SQL多次查询的窄片进行比较。

  3. 我从来没有对此进行任何基准测试,看看临界点在哪里,但你可以想象你有两个表Table1和Table2的情况,每个表有100列,Table1中有1,000行数据与表2的一对多关系,并且对于表1中的每个记录,通常在表2中产生10个匹配。现在,如果您编写一个视图以将所有这些结果拉回到单个查询中,您将期望大约10,000行数据,大约200列宽。通过发出两个单独的查询,无论是通过Linq到SQL还是任何其他机制,您可以从Table1获取最初1,000行100列宽的结果,然后选择剩余的Table2项可能10,000行再增加100列,总计1,100,000个单元格(这远远低于SQL View中的2,000,000个单元格。如果我们假设多对多关系的相关行之间存在很大程度的重叠,那么这些好处就更加夸大了。在最极端的情况下,有100%的重叠意味着我们只能期望总共100,010个数据单元被拉回,这远远小于平坦视图返回的2,000,000个数据。