2015-04-24 133 views
5

我想了解为什么加入我的情况比使用导航属性的语句更快。我有两个疑问。实体框架性能连接与导航属性

先用导航属性:

  var result = (from users in context.MetricBloodPreasure 
       orderby users.User.LastName, users.User.FirstName 
       select new 
       { 
        UserName = users.User.LastName + ", " + users.User.FirstName, 
        Date = users.DateOfValue, 
       }).ToList(); 

Generatet SQL:

SELECT 
    [Project1].[C1] AS [C1], 
    [Project1].[C2] AS [C2], 
    [Project1].[DateOfValue] AS [DateOfValue] 
    FROM (SELECT 
     [Extent1].[DateOfValue] AS [DateOfValue], 
     [Extent2].[FirstName] AS [FirstName], 
     [Extent2].[LastName] AS [LastName], 
     1 AS [C1], 
     CASE WHEN ([Extent2].[LastName] IS NULL) THEN N'' ELSE [Extent2].[LastName] END + N', ' + CASE WHEN ([Extent2].[FirstName] IS NULL) THEN N'' ELSE [Extent2].[FirstName] END AS [C2] 
     FROM [dbo].[MetricBloodPreasure] AS [Extent1] 
     INNER JOIN [dbo].[User] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id] 
    ) AS [Project1] 
    ORDER BY [Project1].[LastName] ASC, [Project1].[FirstName] ASC 

第二位加盟:

var result1 = (from u in context.User 
       orderby u.LastName, u.FirstName 
       join us in context.MetricBloodPreasure 
        on u.Id equals us.UserId into users 
       from s in users 
       select new 
       { 
        UserName = s.User.LastName + ", " + s.User.FirstName, 
        Date = s.DateOfValue, 
       }).ToList(); 

生成的SQL:

SELECT 
    1 AS [C1], 
    CASE WHEN ([Extent1].[LastName] IS NULL) THEN N'' ELSE [Extent1].[LastName] END + N', ' + CASE WHEN ([Extent1].[FirstName] IS NULL) THEN N'' ELSE [Extent1].[FirstName] END AS [C2], 
    [Extent2].[DateOfValue] AS [DateOfValue] 
    FROM [dbo].[User] AS [Extent1] 
    INNER JOIN [dbo].[MetricBloodPreasure] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[UserId]) AND ([Extent2].[UserId] = [Extent1].[Id]) 

在运行第一个查询之前,请拨打var user = context.User.FirstOrDefault();,因为我认为与数据库的开放连接需要一些时间。

结果: 导航属性查询:00:00:00.6719646 加入查询:00:00:00.4941169

看结果似乎LINQ查询在使用连接,而不是导航性能更快。这是真的还是我做错了什么?

+0

您还需要在查询之间清除数据库中的缓存,以便在调用ToList()时获得正确的结果。将查询结构从实现中分离出来并进行基准测试。 –

+0

OrderBy在第二个查询中似乎没有考虑到。这可能是导致差异的原因,你可以尝试'...从用户的命令u.LastName,u.FirstName ...' – jbl

回答

2

为了更好地了解它在做什么,您应该获得原始SQL,并且您可以自己查看执行计划。

要做到这一点,您可以使用SQL事件探查器,看看有什么查询正在运行,也可以通过做这样的事情在运行查询之前登录的SQL查询本身:

context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s); 

也做的一个简单的基准就像你每次运行一样,不一定是可靠的。你会想多次运行它,并平均事情。你也应该按照相反的顺序来运行它们,看看它是否也会改变。

+0

此外插入更多的数据到数据库是好主意,这应该突出显示差异(如果存在) –

+0

这两个查询都返回了超过9000行...是的,我使用日志并运行我的数据库上下文的新实例的查询。加入仍然更快。 – puko

+0

你可以发布正在运行的SQL到原始问题吗?另外,你有没有在SSMS中运行SQL并打开执行计划,以便你能看到差异在哪里? –