通过大量一对多映射提高查询性能
Posted
技术标签:
【中文标题】通过大量一对多映射提高查询性能【英文标题】:Increase performance on query with a lot of one-to-many mappings 【发布时间】:2011-07-29 19:14:17 【问题描述】:我在 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 覆盖以用于排序。关键是分页查询在这种情况下效果不佳,因为排序不是基于 int 或日期(对吗?)
在我们的应用程序的其余部分中,我们显示的关于每个任务的信息较少,而 Linq2Entities 工作得很好。在这种情况下,对象映射正在杀死我们。我已经走上了使用 Dapper 直接进入数据库的道路,但一对多映射有它的警告。对于一些关系,我认为它会运作良好,但不适用于 5-6。我接下来要看的是 PetaPoco,但没走多远,我就想我最好先把这个问题放在这里。
我想带回这么多数据是不是疯了?我有哪些选择可以从中获得最大性能?因为它只是应用程序的一个领域,所以我会稍微复杂一点。
【问题讨论】:
“我想带回这么多数据是不是疯了?”好吧,你正在做相当于SELECT *
。这真的是你需要的吗?还是您只需要每个字段中的几个字段?如果是这样,投影到视图模型上会快得多。
不,你说得对,我只需要几个字段。你是说我应该做 .Select(new TaskViewModel...); 而不是 .ToList()在这种情况下,EF 会编译更高效的查询吗?
Yes, by far.。这不是唯一更快的事情。试试看!
是的,我会试一试。也许我把问题复杂化了。我使用 ViewModel 但不直接投影到它。感谢您的帮助。
@Naor:他可以,但是延迟加载的 N+1 性能可能是最慢的选项。延迟加载是 ORM 在性能方面名声不佳的原因。
【参考方案1】:
我敢打赌,您的 EF 查询拉回了太多数据。问题是,“最佳”检索技术在很大程度上取决于所提取数据的类型和数量。
预先了解这一点可以让您根据预期的数据集调整您运行的查询。
例如...如果您只提取有限数量的具有大量子实体的实体,那么我在这里编写的模式效果很好:
How do I map lists of nested objects with Dapper
如果您知道要提取的 id 并且少于 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
将关系映射到所有关联表。
【讨论】:
以上是关于通过大量一对多映射提高查询性能的主要内容,如果未能解决你的问题,请参考以下文章