我们使用Asp.net Web API构建了一个Web服务。我们使用NHibernate作为连接MySQL数据库的ORM。
我们有几种控制器方法可以执行大量(1,000-3,000)相对便宜的查询。
我们正在寻求提高这些控制器方法的性能,几乎所有的时间都花在了NHibernate查询上,这就是我们关注的重点。
从中期来看,解决方案就像减少查询数量(可能通过减少更大的查询)和/或并行化查询(这需要一些工作,因为NHibernate没有异步api,会话是单一的这样的事情。
从短期来看,我们正在考虑提高绩效而不接受任何一个大型项目。
我们已经完成了一些性能分析,并且惊讶地发现每次查询(超过一半)的大部分时间都花在打开与MySQL的连接上。
似乎NHibernate为每个查询打开了一个与MySQL的新连接,并且每次打开连接时,MySqlConnection.Open()都会对数据库进行两次往返(即使连接来自池)。 / p>
以下是我们的一个效果配置文件的屏幕截图,您可以在其中看到以下两点:
我们想知道这是否是预期的,或者我们是否遗漏了诸如NHibernate的错误配置/误用或者在MySqlConnection.Open()中消除两次往返数据库的方法。
我做了一些额外的挖掘,发现了一些有趣的东西:
如果我们将.SetProperty(Environment.ReleaseConnections, "on_close")
添加到NHibernate配置中,则不再调用Open(),并且执行查询所需的时间会下降超过40%。
但似乎这不是推荐的设置:http://nhibernate.info/doc/nhibernate-reference/transactions.html#transactions-connection-release
基于我希望获得相同行为的文档(没有额外的Open()调用)如果我将读取包装在单个NHibernate事务中但我无法使其工作。这就是我在控制器方法中所做的:
using (var session = _sessionFactory.OpenSession()) {
using (var transaction = session.BeginTransaction()) {
// controller code
transaction.Commit();
}
}
有关如何使用NHibernate的推荐配置获得相同行为的任何想法?
在进一步深入研究之后,我的测试实现中出现了一个错误,在使用事务修复之后,消除了对预期的Open()的额外调用。
答案 0 :(得分:1)
并行化查询(自NHibernate以来需要一些工作 没有异步api,会话是单线程的)和 这样的事情。
您可以使用NHibernate Futures,
推迟查询的执行以下代码(摘自reference文章)将执行单个查询,尽管检索到2个值,
String s = "-i" + " " + mVideoUri.toString().replace("file:///", "") + " -filter_complex [1:v][0:v]scale2ref=iw:ih[ovr][base];[ovr]colorchannelmixer=aa=0.7[ovrl];[base][ovrl]overlay[v] -ss -to -map [v]" + directoryToStore + "/" + FileName + mp4;
String[] arguments = s.split(" ");
ExecuteFFMPEG(arguments);
您还可以使用NHibernate Batching来减少查询次数