2

我正在使用 Entity Framework 4(数据库优先)开发电影数据库应用程序,将大约 8,200 行加载到列表中需要 30 秒。涉及三个表,当我使用 .Include() 时,性能下降得更多——加载 8,200 行几乎需要三分钟。这很痛苦。鉴于我一次学习了很多技术,我希望有一个简单的解决方法。以下是详细信息:

表 1 - 视频

这是一个大表,有 31 列,大约 7,800 行视频。它使用 Guid 作为其主键。

表 2 - ActorsVideos(连接表)

该表有两列:(1) VideoID 列,和 (2) ActorID 列。这两列都是 Guid,分别是 Video 和 Actor 表的外键。此表使用复合主键,其中两列都充当主键。EF4 不对这个表建模;但是,它会创建一个导航属性。该表允许用户为电影分配任意数量的演员。

表 3 - 参与者

有 16 列约 400 行。同样,主键是 Guid。

在代码中,我正在读取 Videos 表中的大约 10 列,然后从关联的 Actors 表中读取列。

C# 代码如下所示:

var videos = context.Videos
foreach (var video in videos)
{
    // retrieve 10 or so properties from 'video'

    if (video.Actors.Count > 0)
    {
        foreach (var actor in video.Actors)
        {
            // retrieve some properties on the actor
        }
    }
}

我尝试在 context.Videos 之后添加 .Include("Actors") ,如上所述,性能从可怕变为可怕。

我查看了使用 Include 生成的 SQL,考虑到视频表中的列数,它大约有 2K 的文本。

我是否必须使用主/从模式拆分视频表?我的下一步是缓存演员表并完全避免导航/关联属性。还有其他建议可以加快速度吗?在我看来,它应该在 5-6 秒内运行。

编辑:数据库是 SQL Server CE 3.5。

4

2 回答 2

3

您要求 Entity Framework 加载视频及其所有演员,然后您在应用程序代码中进行过滤。通常,您提取的数据比您需要的要多。我会为您提供 SQL Server(或您正在使用的任何数据库)预过滤器:

var videos = context.Videos;
var results = from video in videos
              where video.Actors.count > 10
              group video.Actors by video.VideoID into grouping
          select new
          {
              video.VideoID,
              video.Actors
          };

foreach (var group in results)
{
    foreach (var actor in group.Actors)
    {
        // do stuff
    }
}

加载约 8200 行以及它们在视频表中的相关行应该非常快。我在我的工作中做了一些开发,我必须处理一个包含 5 个表连接的 70+ 百万行测试数据表。这运行了大约半分钟。

但是,它运行速度比您正在执行的操作快得多的原因是因为我在SQL Server内部进行过滤。使用 EF 的等效“程序”程序需要几分钟,因为我在从数据库中提取行之后进行过滤。

可以这样想:您不仅要查询数据库中的每一行,而且还要多次提取甚至不需要多次的数据

于 2012-07-13T01:06:58.680 回答
0

尝试使用急切加载

var videos = context.Videos.Include(v=>v.Actors);
foreach (var video in videos)
{
    foreach (var actor in video.Actors)
    {
    }
}

注意:请注意,查询使用延迟执行,这意味着多次迭代也会多次执行查询。如果您将进行多次迭代,请.AsEnumerable()在迭代之前使用并在本地分配它。此外,分析数据库以查看正在执行的查询将有助于确定您还需要急切地获取什么。您可能会强制 EF 加载不需要的实体。如果是这种情况,那么您的查询应该只投影(通过使用Select(x=> new {...stuff you need... }))必要的数据。

编辑:根据MicrosoftInclude()不能与预测相结合,因此在这种情况下,您需要以不同的方式编写查询。

于 2012-07-13T00:56:11.500 回答