0

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

这是一种我返回很多的方法,因为我必须返回表格,一个带有消息数据,一个带有每个收件人:

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
    };

然后我使用这个 IQueryable 来询问高于某个时间戳和类似操作的消息。

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

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

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# 中会是什么样子?

4

2 回答 2

1

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

例如改变

RecipientMessageId = mr.MessageRecipientId

RecipientMessageId = msg.MessageRecipient.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
    };
于 2013-03-27T18:37:31.517 回答
1

与您手头的具体问题无关(莫霍已经部分回答了)......

您还可以尝试性能提示,尤其是Entity Framework 5 的性能注意事项

最重要的是,下载EF Power Tools - 并检查该generate views功能。

有关更多信息,我几天前发布了更多信息(只是一点点,但可能会有所帮助)。

使用 EF 5 Code First 将视图映射到实体

为什么当我想使用 EF Power 工具查看我的模型时出现错误?

于 2013-04-06T00:29:28.447 回答