我想知道在 sql server 2012 db 中插入/更新/删除的一般性能,数据量有时会达到 20 m。表中的行。
我可以信任 NHibernate 生成最佳查询吗?
我想知道在 sql server 2012 db 中插入/更新/删除的一般性能,数据量有时会达到 20 m。表中的行。
我可以信任 NHibernate 生成最佳查询吗?
简单的答案是:不。NH 无法像使用手写查询那样生成“最佳查询”。
它通常从数据库中获取数据以在内存中创建对象。例如,默认情况下它总是选择表中的所有列。它还尝试通过尝试始终生成具有相同参数的相同查询来优化 SQL 编译时间。
你仍然可以用 HQL、Linq 或 SQL 编写你的手写查询。您通常会失去 ORM 的好处,但如果您的应用程序中只有少数情况是性能关键的并且不是太多面向对象的情况,它就可以完美地工作。
NHibernate 可以做其他你用手写 SQL 很难实现的性能优化。而且这个特性对业务逻辑是透明的,不需要太多特殊的开发工作。
这些功能特别是在延迟加载和批量大小(预取)方面。使用手写 SQL,您必须在业务逻辑中进行大多数性能优化。如果您的业务逻辑很复杂,那么优化的空间就很小,可维护性就会成为一个大问题。在这种情况下,手写 DAL 的性能和可维护性都下降了,而且真的很痛苦。在这种情况下,NHiberate 提供了更好的性能和更好的可维护性。
正如您可能猜到的:如果您的业务逻辑不是很复杂,那么手写 DAL 可以提供可能的最佳性能,而无需过多的可维护性折衷。
因此,请始终为问题选择正确的工具。
示例案例
该应用程序具有处理订单的功能。它获取一个主键作为参数。它使用数据库中的订单项目加载订单,它需要有关用户和产品、位置、税金、邮政费率、特别优惠和诸如此类的信息。所以这是一件非常复杂的事情。查询优化不是什么大问题,因为大多数查询从本质上来说都是微不足道的。
四年后,您的老板想要一个“批处理”,您可以在其中处理数百个订单。所以你必须循环调用你的函数。第一个问题:您可以通过优化查询获得要处理的订单。但是您的函数将主键作为参数并再次加载订单。下一个问题:需要为每个订单再次加载所有关于产品、位置等的相关数据,即使它们在大多数情况下是相同的(但并非总是如此)。所以它开始表现得很糟糕。您尝试为已从数据库加载的内容实现一些缓存。很难管理对这些数据的更改,因为您在数据库中有一个版本,在缓存中有一个版本。所以你尽你最大的努力,直到它表现得足够好,而你失去了对“批处理”之前非常好的代码的控制权。
使用 NHibernate,它看起来有很大不同。您不必传递主键。您有从数据库仅加载一次的对象(可能是代理并且仅包含主键)。当从订单导航到产品、位置和所有内容时(与使用其他查询相反),对象在第一次使用时仅加载一次。由于可配置批量大小,NH 会为稍后处理的一些订单预取产品、位置等,因此它避免了额外的查询。您的代码基本上只包含您需要执行的计算,并且没有提高性能所需的复杂内容。(好吧,这就是它在完美世界中的样子,但实际上它非常好)。
使用 NHibernate 或任何 ORM 是一种选择,与使用 SQL 和 SP 的代码相比,大多数情况下选择具有更易于维护的代码。
在某些情况下,与 SP 相比,它生成查询的速度可能不够快,而且其中许多情况可能没有明显的性能问题。但是,如果不是这种情况,您始终可以使用 SP 并使用 NHibernate 调用 SP。
你不应该盲目相信它。在 NHibernate 中有许多优化查询的方法,例如用于查询的多个 API,包括生成 HQL 或 SQL 查询的能力。
有各种分析工具,包括NHibernate Profiler,可用于监控查询和一般性能。
还有IStatelessSession
专为批量操作而设计的。
这取决于您所说的最佳查询以及您的数据模型如何适合您的数据库模型(表)。
您可以记录所有语句,因此 NHibernate 正在做什么以及它用于查询或更新数据库的 SQL 语句是透明的。
NHibernate 为您提供了许多选项来调整您的查询。一些可能性是有状态与无状态会话、交易、HQL、期货。
如果这仍然不起作用,您可以直接从 NHibernate 调用 SQL 语句。这样做的缺点是,如果这对您很重要,您将失去将代码很容易移植到另一个数据库的能力。