我最近开始使用Entity Framework并编写代码首次迁移。我的应用程序现在“正常”,我开始看到事情变得缓慢。我的数据库在表中有大约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#中会看到什么?
答案 0 :(得分:1)
您不需要linq查询中的连接 - 只需访问投影中的msg.MessageRecipient nav属性即可。它将通过减少返回到您在投影中使用的字段的数量来简化SQL语句,但仍然需要连接。
e.g。变化
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
};
答案 1 :(得分:1)
与你手头的具体问题无关(莫霍已经部分回答了)......
您还可以尝试performance tips,尤其是Performance Considerations for Entity Framework 5
最重要的是,下载EF Power Tools - 并查看
generate views
功能。
有关更多信息,我几天前发布了一些更多的信息(只是一点但可能有帮助)。
Mapping View to Entity using EF 5 Code First
why when i want use EF Power tools for view my model i get error?