C# 实体框架连接优化

C# 实体框架连接优化,c#,sql-server-2008,entity-framework,code-first,C#,Sql Server 2008,Entity Framework,Code First,我最近开始使用实体框架和代码优先迁移。我的应用程序现在是实时的,我开始看到事情变得越来越慢。我的数据库表中大约有30000行是使用最多的 这是一种我必须返回很多表的方法,一个包含消息数据,另一个包含每个收件人: IQueryable<CompleteMessageModel> completeMessageModels = from msg in db.NewMessageItems join mr in db.MessageRecipients on msg.Me

我最近开始使用实体框架和代码优先迁移。我的应用程序现在是实时的,我开始看到事情变得越来越慢。我的数据库表中大约有30000行是使用最多的

这是一种我必须返回很多表的方法,一个包含消息数据,另一个包含每个收件人:

IQueryable<CompleteMessageModel> completeMessageModels = 
    from msg in db.NewMessageItems
    join mr in db.MessageRecipients on msg.MessageId equals mr.MessageId
    select
    new CompleteMessageModel()
    {
          MessageId = msg.MessageId,
          RecipientMessageId = mr.MessageRecipientId,
          Title = msg.Title,
          Message = msg.Message,
          Recipients = msg.Recipients,
          AuthorUserId = msg.AuthorId,
          RecipientUserId = mr.RecipientId,
          StatusCode = mr.StatusCode,
          Timestamp = msg.Timestamp,
          IsRead = mr.ReadTimestamp > 0,
          ReadTimestamp = mr.ReadTimestamp,
          GeoTag = msg.GeoTag
    };
然后我使用这个iQueryEnable请求超过某个时间戳的消息和类似的操作

我的问题是:这个查询可以进一步优化吗

这是最常用查询的执行计划:

SELECT TOP (90) 
[Project1].[MessageId] AS [MessageId], 
[Project1].[MessageRecipientId] AS [MessageRecipientId], 
[Project1].[Title] AS [Title], 
[Project1].[Message] AS [Message], 
[Project1].[Recipients] AS [Recipients], 
[Project1].[AuthorId] AS [AuthorId], 
[Project1].[RecipientId] AS [RecipientId], 
[Project1].[StatusCode] AS [StatusCode], 
[Project1].[Timestamp] AS [Timestamp], 
[Project1].[C1] AS [C1], 
[Project1].[ReadTimestamp] AS [ReadTimestamp], 
[Project1].[GeoTag] AS [GeoTag]
FROM ( SELECT 
    [Extent1].[MessageId] AS [MessageId], 
    [Extent1].[Message] AS [Message], 
    [Extent1].[Title] AS [Title], 
    [Extent1].[AuthorId] AS [AuthorId], 
    [Extent1].[Timestamp] AS [Timestamp], 
    [Extent1].[Recipients] AS [Recipients], 
    [Extent1].[GeoTag] AS [GeoTag], 
    [Extent2].[MessageRecipientId] AS [MessageRecipientId], 
    [Extent2].[RecipientId] AS [RecipientId], 
    [Extent2].[ReadTimestamp] AS [ReadTimestamp], 
    [Extent2].[StatusCode] AS [StatusCode], 
    CASE WHEN ([Extent2].[ReadTimestamp] > 0) THEN cast(1 as bit) WHEN ( NOT ([Extent2].[ReadTimestamp] > 0)) THEN cast(0 as bit) END AS [C1]
    FROM  [dbo].[NewMessageModels] AS [Extent1]
    INNER JOIN [dbo].[MessageRecipients] AS [Extent2] ON [Extent1].[MessageId] = [Extent2].[MessageId]
    WHERE ([Extent2].[RecipientId] = @p__linq__0) AND (1 <> [Extent2].[StatusCode]) AND (3 <> [Extent2].[StatusCode]) AND ([Extent1].[Timestamp] >= @p__linq__1)
)  AS [Project1]
ORDER BY [Project1].[Timestamp] DESC

如果它可以被优化,在c语言中会是什么样子

在linq查询中不需要连接-只需访问投影中的msg.MessageRecipient nav属性即可。它将简化SQL语句,将返回的字段数减少为仅在投影中使用的字段数,但联接仍然是必需的

e、 g.变化

RecipientMessageId = mr.MessageRecipientId

检查SSMS中生成的脚本的执行计划-它应该建议一个可以提高性能的索引

编辑:修改示例以删除不必要的linq联接。您可以像访问投影中的任何其他属性一样访问导航属性:

IQueryable<CompleteMessageModel> completeMessageModels = 
    from msg in db.NewMessageItems
    //join mr in db.MessageRecipients on msg.MessageId equals mr.MessageId
    select
    new CompleteMessageModel()
    {
          MessageId = msg.MessageId,
          RecipientMessageId = msg.MessageRecipient.MessageRecipientId,
          Title = msg.Title,
          Message = msg.Message,
          Recipients = msg.Recipients,
          AuthorUserId = msg.AuthorId,
          RecipientUserId = msg.MessageRecipient.RecipientId,
          StatusCode = msg.MessageRecipient.StatusCode,
          Timestamp = msg.Timestamp,
          IsRead = msg.MessageRecipient.ReadTimestamp > 0,
          ReadTimestamp = msg.MessageRecipient.ReadTimestamp,
          GeoTag = msg.GeoTag
    };

与您手头的特定问题无关,莫霍已经部分回答了这些问题

你也可以试试这个,尤其是

最重要的是,下载 -并选中“生成视图”功能

为了获得更多的信息,我几天前发布了一些更多的信息,只是一点点,但可能会有所帮助


谢谢你宝贵的答复。如何访问投影中的属性?您是否有代码示例或链接来演示如何执行此操作?尽管您可以使用导航属性,但查询本身无法优化。您已经使用了一个投影,它缩小了结果集的范围,并且需要连接。这一定是一个索引问题。三万行算不了什么。或者其中一个字段是一个大对象消息,可能?。每个NewMessageItems可能有许多MessageRecipients,我不知道如何让msg.MessageRecipient在没有联接的情况下工作?msg上也没有MessageRecipient对象;当它找到索引时,我如何使用它?谢谢你迄今为止的帮助!
IQueryable<CompleteMessageModel> completeMessageModels = 
    from msg in db.NewMessageItems
    //join mr in db.MessageRecipients on msg.MessageId equals mr.MessageId
    select
    new CompleteMessageModel()
    {
          MessageId = msg.MessageId,
          RecipientMessageId = msg.MessageRecipient.MessageRecipientId,
          Title = msg.Title,
          Message = msg.Message,
          Recipients = msg.Recipients,
          AuthorUserId = msg.AuthorId,
          RecipientUserId = msg.MessageRecipient.RecipientId,
          StatusCode = msg.MessageRecipient.StatusCode,
          Timestamp = msg.Timestamp,
          IsRead = msg.MessageRecipient.ReadTimestamp > 0,
          ReadTimestamp = msg.MessageRecipient.ReadTimestamp,
          GeoTag = msg.GeoTag
    };