我有一个使用NHibernate作为对象关系管理的应用程序,由于它访问数据的方式,它有时会遇到性能问题。可以做哪些事情来提高NHibernate的性能?(请将每个答案限制为一个建议)
发布于 2008-09-15 22:03:11
使用NHibernate可能会遇到的第一个也是最显著的性能问题是,如果要为创建的每个会话创建一个新的会话工厂。每次执行应用程序时,应该只创建一个会话工厂实例,所有会话都应该由该工厂创建。
按照这些思路,您应该继续使用相同的会话,只要它有意义。这将因应用程序而异,但对于大多数web应用程序,建议每个请求使用一个会话。如果你经常丢弃你的会话,你不会从它的缓存中得到好处。智能地使用会话缓存可以将查询数为线性(或更差)的例程更改为常量,而无需做太多工作。
同样重要的是,您希望确保您正在延迟加载对象引用。如果不是这样,即使是最简单的查询,也可以加载整个对象图。只有某些原因不这样做,但从延迟加载开始并根据需要切换回来总是更好的。
这给我们带来了急切的抓取,这是与懒惰加载相反的。在遍历对象层次结构或循环遍历集合时,很容易忘记您正在进行的查询数量,并最终得到指数级数量的查询。可以使用FETCH JOIN在每个查询的基础上执行即时获取。在极少数情况下,例如,如果有一对特定的表,您总是获取连接,请考虑关闭该关系的延迟加载。
一如既往,SQL事件探查器是查找运行缓慢或重复执行的查询的好方法。在我的上一份工作中,我们有一个开发功能,可以计算每个页面请求的查询次数。对例程的大量查询是例程不能很好地与NHibernate一起工作的最明显标志。如果每个例程或请求的查询数看起来不错,那么您可能正在进行数据库调优;确保有足够的内存在缓存中存储执行计划和数据,正确地对数据进行索引,等等。
我们遇到的一个棘手的小问题是SetParameterList()。该函数允许您轻松地将参数列表传递给查询。NHibernate通过为传入的每个项目创建一个参数来实现这一点。这会导致每个参数的查询计划都不同。我们的执行计划几乎总是从缓存中释放出来。此外,过多的参数会显著降低查询速度。我们对NHibernate进行了自定义修改,在单个参数中以分隔列表的形式发送项目。在SQL Server中,该列表由一个表值函数分隔,我们的hack自动将该函数插入到查询的in子句中。根据您的应用程序,可能会有其他类似的地雷。SQL Profiler是查找它们的最佳方法。
发布于 2008-10-26 23:27:29
NHibernate的SessionFactory是一个开销很大的操作,所以一个好的策略是创建一个单例来确保内存中只有一个SessionFactory实例:
public class NHibernateSessionManager
{
private readonly ISessionFactory _sessionFactory;
public static readonly NHibernateSessionManager Instance = new NHibernateSessionManager();
private NHibernateSessionManager()
{
if (_sessionFactory == null)
{
System.Diagnostics.Debug.WriteLine("Factory was null - creating one");
_sessionFactory = (new Configuration().Configure().BuildSessionFactory());
}
}
public ISession GetSession()
{
return _sessionFactory.OpenSession();
}
public void Initialize()
{
ISession disposeMe = Instance.GetSession();
}
}
然后,您可以在Global.Asax Application_Startup中对其进行初始化:
protected void Application_Start()
{
NHibernateSessionManager.Instance.Initialize();
}
发布于 2008-12-02 20:03:11
对于执行缓慢的查询,通过识别何时从延迟加载切换到急切获取来避免和/或最小化Select N + 1 problem。
https://stackoverflow.com/questions/67103
复制相似问题