通过大量一对多映射提高查询性能

时间:2011-07-29 19:14:17

标签: sql-server entity-framework dapper petapoco

我正在使用Entity Framework到SQL Azure,在我的应用程序的一个页面中,我们向用户显示了相当多的相关数据。我们在页面上最多加载30个项目,但每个项目与其他对象有5个一对多映射。查询时间处于合理的水平但我在对象映射上泄漏了相当多的性能。 (几乎整整一秒)。

以下是我的对象的示例

public class Task
{
    public string Name {get; set;}
    public string Status {get; set;}
    public DateTime DueDate {get; set;}
    public IEnumerable<TaskData> Data {get; set;}
    public IEnumerable<Transaction> Transactions {get; set;}
    public IEnumerable<File> Files {get; set;}
    public IEnumerable<Comment> Comments {get; set;}
    public IEnumerable<People> People {get; set;}
}

任务具有名称,状态和截止日期。它还有很多 TaskData,它们是自定义名称/值对,很多显示任务历史记录的事务,很多文件,许多评论和许多人员正在努力。

我的EF查询看起来像这样。

var Items = context.Items.Include(x=>x.Data).Include(x=>x.Files).Include(x=>x.Comments).Include(x=>x.People).Where(some constraint).ToList();

特定任务的相关性首先取决于状态,然后是截止日期。所以我创建了一个IComparable覆盖来与sort一起使用。关键是分页查询在这种情况下不能很好地工作,因为排序不是基于int或日期(我是对的吗?)

在我们的其他应用程序中,我们显示的每项任务信息较少,Linq2Entities工作得很好。在这种情况下,对象映射正在杀死我们。我已经走上了与Dapper直接进入数据库的道路,但是一对多的映射有它的警告。对于一些关系,我认为它会很好但不适合5-6。我接下来要看的是PetaPoco,但是在我认为我最好先把问题放在这里之前我没有走得太远。

我是否因为试图带回这么多数据而疯狂?我有什么选择可以获得最大的性能?因为它只是应用程序的一个区域,所以我会稍微复杂一些。

1 个答案:

答案 0 :(得分:2)

我愿意打赌你的EF查询正在撤回过多的数据。问题是,“最佳”检索技术在很大程度上取决于所拉取数据的类型和数量。

预先知道您可以根据预期的数据集调整运行的查询。

例如......如果你只是拉动有限数量的具有大量子实体的实体,我在这里写的模式效果很好:

How do I map lists of nested objects with Dapper

如果你知道你正在拉什么,而且数量少于2000,你可以通过查询单个网格并使用QueryMultiple进行映射来快捷方式,例如:

cnn.QueryMultiple(@"select * from Tasks where Id in @ids 
select * from Files where TaskId in @ids
.. etc ..", new {ids = new int[] {1,2,3}});

如果您要更大的集合,则可能需要批处理,或者分阶段进行批处理。


对于您的特定示例,我将查询Tasks以获取所有任务ID和数据,然后使用单个QueryMultiple将关系映射到所有关联表。