首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >提高NHibernate性能的最佳方法是什么?

提高NHibernate性能的最佳方法是什么?
EN

Stack Overflow用户
提问于 2008-09-15 21:22:53
回答 12查看 28.8K关注 0票数 61

我有一个使用NHibernate作为对象关系管理的应用程序,由于它访问数据的方式,它有时会遇到性能问题。可以做哪些事情来提高NHibernate的性能?(请将每个答案限制为一个建议)

EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2008-09-15 22:03:11

使用NHibernate可能会遇到的第一个也是最显著的性能问题是,如果要为创建的每个会话创建一个新的会话工厂。每次执行应用程序时,应该只创建一个会话工厂实例,所有会话都应该由该工厂创建。

按照这些思路,您应该继续使用相同的会话,只要它有意义。这将因应用程序而异,但对于大多数web应用程序,建议每个请求使用一个会话。如果你经常丢弃你的会话,你不会从它的缓存中得到好处。智能地使用会话缓存可以将查询数为线性(或更差)的例程更改为常量,而无需做太多工作。

同样重要的是,您希望确保您正在延迟加载对象引用。如果不是这样,即使是最简单的查询,也可以加载整个对象图。只有某些原因不这样做,但从延迟加载开始并根据需要切换回来总是更好的。

这给我们带来了急切的抓取,这是与懒惰加载相反的。在遍历对象层次结构或循环遍历集合时,很容易忘记您正在进行的查询数量,并最终得到指数级数量的查询。可以使用FETCH JOIN在每个查询的基础上执行即时获取。在极少数情况下,例如,如果有一对特定的表,您总是获取连接,请考虑关闭该关系的延迟加载。

一如既往,SQL事件探查器是查找运行缓慢或重复执行的查询的好方法。在我的上一份工作中,我们有一个开发功能,可以计算每个页面请求的查询次数。对例程的大量查询是例程不能很好地与NHibernate一起工作的最明显标志。如果每个例程或请求的查询数看起来不错,那么您可能正在进行数据库调优;确保有足够的内存在缓存中存储执行计划和数据,正确地对数据进行索引,等等。

我们遇到的一个棘手的小问题是SetParameterList()。该函数允许您轻松地将参数列表传递给查询。NHibernate通过为传入的每个项目创建一个参数来实现这一点。这会导致每个参数的查询计划都不同。我们的执行计划几乎总是从缓存中释放出来。此外,过多的参数会显著降低查询速度。我们对NHibernate进行了自定义修改,在单个参数中以分隔列表的形式发送项目。在SQL Server中,该列表由一个表值函数分隔,我们的hack自动将该函数插入到查询的in子句中。根据您的应用程序,可能会有其他类似的地雷。SQL Profiler是查找它们的最佳方法。

票数 54
EN

Stack Overflow用户

发布于 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();
}
票数 26
EN

Stack Overflow用户

发布于 2008-12-02 20:03:11

对于执行缓慢的查询,通过识别何时从延迟加载切换到急切获取来避免和/或最小化Select N + 1 problem

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档