【发布时间】:2017-05-10 19:01:14
【问题描述】:
我们有一个使用 Asp.net Web API 构建的 Web 服务。我们使用 NHibernate 作为连接 MySQL 数据库的 ORM。
我们有几个控制器方法可以执行大量 (1,000-3,000) 相对便宜的查询。
我们正在考虑提高这些控制器方法的性能,并且几乎所有时间都花在了 NHibernate 查询上,因此这是我们关注的重点。
从中期来看,解决方案是减少查询数量(可能通过减少更大的查询)和/或并行化查询(这需要一些工作,因为 NHibernate 没有异步 api 并且会话是单一的线程)和类似的东西。
在短期内,我们希望在不承担任何一个大型项目的情况下提高性能。
我们进行了一些性能分析,并惊讶地发现每个查询中的很多时间(超过一半)都花在了打开与 MySQL 的连接上。
似乎 NHibernate 正在为每个查询打开一个到 MySQL 的新连接,并且 MySqlConnection.Open() 每次打开连接时都会对数据库进行两次往返(即使连接来自池)。
这是我们的一个性能配置文件的屏幕截图,您可以在其中看到这两件事:
我们想知道这是否是预期的,或者我们是否遗漏了诸如 NHibernate 的错误配置/误用之类的东西,或者是在 MySqlConnection.Open() 中消除到数据库的两次往返的方法。
我做了一些额外的挖掘,发现了一些有趣的东西:
如果我们将.SetProperty(Environment.ReleaseConnections, "on_close") 添加到 NHibernate 配置中,则不再调用 Open(),并且执行查询所需的时间减少了 40% 以上。
这似乎不是推荐的设置:http://nhibernate.info/doc/nhibernate-reference/transactions.html#transactions-connection-release
根据文档,如果我将读取包装在单个 NHibernate 事务中,我希望得到相同的行为(无需额外调用 Open()),但我无法让它工作。这是我在控制器方法中所做的:
using (var session = _sessionFactory.OpenSession()) {
using (var transaction = session.BeginTransaction()) {
// controller code
transaction.Commit();
}
}
关于如何使用 NHibernate 的推荐配置获得相同行为的任何想法?
在深入研究之后发现我的测试实现中有一个错误,在使用事务修复它之后,按预期消除了对 Open() 的额外调用。
【问题讨论】:
标签: mysql asp.net-web-api nhibernate