实体框架如何处理大量记录? [关闭]
Posted
技术标签:
【中文标题】实体框架如何处理大量记录? [关闭]【英文标题】:How entity framework works for large number of records? [closed] 【发布时间】:2013-10-19 03:23:32 【问题描述】:我已经看到一个未回答的问题here on。
我的问题是-
EF 真的为大型应用程序做好了生产准备吗?
问题源于这些基本问题 -
-
EF 将所有记录拉入内存然后执行查询
手术。当表有大约 1000 条记录时,EF 会如何表现?
对于简单的编辑,我必须拉记录编辑它并
然后使用
SaveChanges()
推送到数据库
【问题讨论】:
1) EF 不会将所有记录拉入内存进行查询。 2) 好的……这与大规模应用程序有什么关系? 不要混用:要更新的大数据与大应用程序。 EF对于日常数据操作非常方便,例如显示、编辑、添加单条记录。它没有针对批量插入/更新操作进行优化,但是对此进行了讨论、尝试和解决方案。请参阅this SO Q&A 了解更多信息。 @roliu 我们希望确保在只需要更新一个值时不要提取整个元组。 您不应该更改帖子标题和标签。 EF Core 是完全不同的系统,因此您所做的所有当前答案都无效。您应该回复它们并提出一个新问题。 【参考方案1】:我遇到过类似的情况,我们有一个大型数据库,其中包含许多表,每个表包含 7 到 1000 万条记录。我们使用实体框架来显示数据。为了获得出色的表现,这就是我学到的; 我的 10 条实体框架黄金法则:
了解仅在需要实际记录时才调用数据库。所有操作都只是用来进行查询(SQL),所以尽量只获取一条数据而不是请求大量记录。尽可能修剪 fetch 大小
是的,(在某些情况下存储过程是更好的选择,它们并不像某些人认为的那样邪恶),您应该在必要时使用存储过程。将它们导入您的模型并为它们导入函数。也可以直接调用它们 ExecuteStoreCommand()、ExecuteStoreQuery()。函数和视图也是如此,但 EF 有一种非常奇怪的调用函数“SELECT dbo.blah(@id)”的方式。
EF 在必须填充具有较深层次结构的实体时执行速度较慢。对层次结构较深的实体要格外小心
有时,当您请求记录并且不需要修改它们时,您应该告诉 EF 不要查看属性更改 (AutoDetectChanges)。这样记录检索要快得多
数据库的索引很好,但在 EF 的情况下它变得非常重要。您用于检索和排序的列应正确编入索引。
当你的模型很大时,VS2010/VS2012 模型设计师会变得非常疯狂。所以把你的模型分成中型模型。存在一个限制,即来自不同模型的实体不能共享,即使它们可能指向数据库中的同一个表。
当您必须在不同位置对同一个实体进行更改时,请使用同一个实体,进行更改并只保存一次。关键是要避免检索相同的记录,进行更改并多次保存。 (真正的性能提升提示)。
当您只需要一两列中的信息时,尽量不要获取完整的实体。你可以直接执行你的 sql 或者有一个迷你实体。您可能还需要在应用程序中缓存一些常用数据。
交易很慢。小心他们。
SQL Profiler 或任何查询分析器都是您的朋友。在开发应用程序时运行它以查看 EF 发送到数据库的内容。当您在您的应用程序中使用 LINQ 或 Lambda 表达式执行连接时,EF 通常会生成一个 Select-Where-In-Select 样式的查询,该查询可能并不总是表现良好。如果您发现任何此类情况,请卷起您的袖子,在 DB 上执行连接并让 EF 检索结果。 (这个我忘了,最重要的!)
如果您牢记这些事情,EF 应该提供与普通 ADO.NET 几乎相似的性能(如果不一样的话)。
【讨论】:
第 8 条:获取 AutoMapper 并使用Project().To<>()
。
2.你必须使用存储过程?我想远离 SPROC,因为那不是 EF 真的是它。我可以只使用 dapper 或其他东西,并且只对所有东西使用 SPROC,甚至不用担心 EF 或任何东西。
@ppumkin:在某些情况下,您无法有效地从 EF 发出语句。在这种情况下,存储过程可以提供帮助。但这真的是你的选择。如果你可以在不使用 SP 的情况下实现你的目标,那就不要费心使用它们了。
是的。但是2,一年后,我可以得出结论,你不能再使用SP了。但问题是,数据库设计者受到了威胁,因为这是他们能控制的最后一件事。但是他们不明白数据库设计已经改为维护。开发人员定义模型,EF 构建数据库和查询,而数据库人员只需要确保数据库快速运行并正确设置索引。我不再使用 SP、TSQL 或 SSMS,我的项目具有高度可扩展性和极快的速度。数字 2 不正确。
我在做一个银行应用,SP 帮了大忙。我不能说“嘿!我们现在正在使用 ORM,所以让我们扔掉所有已经工作多年的忠实存储过程,让我们从头开始用 EF 编写所有这些”——“为什么?” - “因为我爱英孚!”。至于“DEV 定义模型,EF 构建数据库和查询,并且 DB FOLK 只需要确保数据库运行快速” - 这可能是您的情况,但对于企业级应用程序、表、SP、函数由单独的开发人员维护我们称使用 TSQL 和 PLSQL 专业知识的 DB 开发人员。希望你一定听说过他们!【参考方案2】:
1. EF 将所有记录拉入内存,然后执行查询操作。当表有大约 1000 条记录时,EF 会如何表现?
这不是真的! EF 只获取必要的记录,查询被转换为适当的 SQL 语句。 EF 可以在 DataContext
内本地缓存对象(并跟踪对实体所做的所有更改),但只要您遵循规则仅在需要时保持上下文打开,就不会出现问题。
2。对于简单的编辑,我必须拉记录编辑它,然后使用 SaveChanges() 推送到数据库
是的,但我不会打扰这样做,除非您真的看到性能问题。因为 1. 不正确,所以在保存之前您只会从数据库中获取一条记录。您可以通过将 SQL 查询创建为字符串并将其作为纯字符串发送来绕过它。
【讨论】:
谢谢,我可以相信 EF 在加入多个表时不会在内存操作中执行吗? 在 SQL 中使用 EF 对多个表进行非常复杂的联接是非常有可能的,但是可能需要一些经验来避免一些意外的内存联接。 Entity Linq 的学习曲线比较浅,但也正因为如此,也有很多陷阱。 这个答案具有误导性。是的,EF 确实在内存中执行连接如果它有一组作为查询的一部分或内存列表提供的值,基本上对于任何不是来自数据库的内容,EF 将从数据库中提取所有内容,执行操作在内存中并返回结果。如果您想进行实验,请使用列表或数组执行表连接并查看其行为方式。到目前为止,对于 EF 6.0,这仍然是正确的。【参考方案3】:-
EF 将您的 LINQ 查询转换为 SQL 查询,因此它不会将所有记录拉入内存。生成的 SQL 可能并不总是最有效的,但一千条记录根本不是问题。
是的,这是一种方法(假设您只想编辑一条记录)。如果您要更改多条记录,则可以使用一个查询将它们全部获取,
SaveChanges()
将保留所有这些更改。
【讨论】:
【参考方案4】:EF 不是一个糟糕的 ORM 框架。这是一个不同的,有自己的特点。将 Microsoft Entity Framework 6 与由 Microsoft Enterprise Library 6 提供支持的 NetTiers 进行比较。
这是两种完全不同的野兽。公认的答案非常好,因为它体现了 EF6 的细微差别。要理解的关键是每个 ORM 都有自己的长处和短处。将项目需求及其数据访问模式与 ORM 的行为模式进行比较。
例如:NetTiers 将始终为您提供比 EF6 更高的原始性能。然而,这主要是因为它不是一个点击 ORM 并且作为生成 ORM 的一部分,您将优化您的数据模型,在相关的地方添加自定义存储过程,等等......如果您使用相同的设计数据模型EF6 的努力可能会接近相同的性能。
还可以考虑修改ORM吗?例如,使用 NetTiers,您可以向 codesmith 模板添加扩展,以在基本 ORM 库生成的内容之外包含您自己的设计模式。
还要考虑 EF6 大量使用反射,而 NetTiers 或任何由 Microsoft Enterprise Library 提供支持的库将大量使用泛型。这是两种完全不同的方法。为什么这样?因为 EF6 基于动态反射,而 NetTiers 基于静态反射。哪个更快哪个更好完全取决于 ORM 所需的使用模式。
有时混合方法效果更好:考虑例如用于 Web API OData 端点的 EF6、一些使用 NetTiers 和 Microsoft 企业库以及自定义存储过程包装的大型表,以及一些使用自定义构建的直写对象包装的大型主数据表缓存,在初始加载时,使用 ADO 数据读取器将记录集流式传输到内存缓存中。
这些都是不同的,它们都有最适合的场景:EF6、NetTiers、NHibernate、Wilson OR Mapper、来自 Dev Express 的 XPO 等...
【讨论】:
【参考方案5】:您的问题没有简单的答案。主要是关于你想用你的数据做什么?您一次需要这么多数据吗?
EF 将您的查询转换为 SQL,因此此时内存中没有对象。当您获取数据时,选定的记录就在内存中。如果您要选择大量大型对象,那么如果您需要对它们进行全部操作,这可能会成为性能杀手。
如果您不需要全部操作它们,您可以禁用更改跟踪,稍后为您需要操作的单个对象启用它。
所以您看到这取决于您的应用程序类型。 如果您需要高效处理大量数据,请不要使用 OR-Mapper!
否则 EF 也可以,但请考虑一下您一次真正需要多少对象以及您想用它们做什么。
【讨论】:
以上是关于实体框架如何处理大量记录? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
MVC4+EFcodefirst中如何处理数据库历史记录的保存和查询
如何处理Tomcat日志catalina.out日志文件过大的问题
如何处理循环引用 - 或 - 在 WCF 服务中返回的第一级子项下的引用暴露实体框架数据模型?
如何使用实体框架将大量数据延迟加载到 GridView [关闭]