I have an application that uses NHibernate as its ORM and sometimes it experiences performance issues due to how the data is being accessed by it. What kind of things can be done to improve the performance of NHibernate? (Please limit to one recommendation per answer)
我有一个应用程序,它使用NHibernate作为它的ORM,有时它会遇到性能问题,因为数据是如何被访问的。有什么方法可以提高NHibernate的性能呢?(请每次回答只推荐一份)
12 个解决方案
#1
49
The first and most dramatic performance problem that you can run into with NHibernate is if you are creating a new session factory for every session you create. Only one session factory instance should be created for each application execution and all sessions should be created by that factory.
NHibernate遇到的第一个、也是最引人注目的性能问题是,如果为创建的每个会话创建一个新的会话工厂。应该为每个应用程序执行创建一个会话工厂实例,并且该工厂应该创建所有会话。
Along those lines, you should continue using the same session as long as it makes sense. This will vary by application, but for most web applications, a single session per request is recommended. If you throw away your session frequently, you aren't gaining the benefits of its cache. Intelligently using the session cache can change a routine with a linear (or worse) number of queries to a constant number without much work.
沿着这些思路,您应该继续使用相同的会话,只要它有意义。这因应用程序而异,但对于大多数web应用程序,建议每个请求使用一个会话。如果你经常丢弃你的会话,你就得不到它缓存的好处。智能地使用会话缓存可以在没有大量工作的情况下,用线性(或更糟)的查询数来改变一个例程。
Equally important is that you want to make sure that you are lazy loading your object references. If you are not, entire object graphs could be loaded for even the most simple queries. There are only certain reasons not to do this, but it is always better to start with lazy loading and switch back as needed.
同样重要的是,您要确保延迟加载对象引用。如果不是,那么即使是最简单的查询也可以加载整个对象图。不这样做是有一定原因的,但是最好从延迟加载开始,然后根据需要进行切换。
That brings us to eager fetching, the opposite of lazy loading. While traversing object hierarchies or looping through collections, it can be easy to lose track of how many queries you are making and you end up with an exponential number of queries. Eager fetching can be done on a per query basis with a FETCH JOIN. In rare circumstances, such as if there is a particular pair of tables you always fetch join, consider turning off lazy loading for that relationship.
这就带来了渴望取回,与惰性装载相反。在遍历对象层次结构或遍历集合时,很容易丢失正在进行的查询的数量,最终得到的查询数量是指数级的。在每个查询基础上都可以使用FETCH JOIN来完成热切的抓取。在很少的情况下,例如如果您总是获取join,那么可以考虑为该关系关闭惰性加载。
As always, SQL Profiler is a great way to find queries that are running slow or being made repeatedly. At my last job we had a development feature that counted queries per page request as well. A high number of queries for a routine is the most obvious indicator that your routine is not working well with NHibernate. If the number of queries per routine or request looks good, you are probably down to database tuning; making sure you have enough memory to store execution plans and data in the cache, correctly indexing your data, etc.
一如既往,SQL Profiler是查找运行缓慢或重复执行的查询的好方法。在我的上一份工作中,我们有一个开发特性,可以计算每个页面请求的查询数。对一个例程的大量查询是表明您的例程在NHibernate中不能正常工作的最明显的标志。如果每个例程或请求的查询数量看起来不错,那么您可能需要对数据库进行调优;确保您有足够的内存来在缓存中存储执行计划和数据,正确地索引数据等等。
One tricky little problem we ran into was with SetParameterList(). The function allows you to easily pass a list of parameters to a query. NHibernate implemented this by creating one parameter for each item passed in. This results in a different query plan for every number of parameters. Our execution plans were almost always getting released from the cache. Also, numerous parameters can significantly slow down a query. We did a custom hack of NHibernate to send the items as a delimited list in a single parameter. The list was separated in SQL Server by a table value function that our hack automatically inserted into the IN clause of the query. There could be other land mines like this depending on your application. SQL Profiler is the best way to find them.
我们遇到的一个棘手的小问题是SetParameterList()。该函数允许您轻松地将参数列表传递给查询。NHibernate通过为传入的每个项创建一个参数来实现这一点。这将导致对每个参数的不同查询计划。我们的执行计划几乎总是从缓存中释放出来。此外,许多参数可以显著降低查询速度。我们对NHibernate做了一个定制的修改,将项目作为带分隔符的列表发送到一个参数中。在SQL Server中,列表被一个表值函数分隔,我们的hack将这个表值函数自动插入到查询的in子句中。根据您的应用,可能还有其他类似的地雷。SQL分析器是找到它们的最佳方法。
#2
25
NHibernate's SessionFactory is an expensive operation so a good strategy is to creates a Singleton which ensures that there is only ONE instance of SessionFactory in memory:
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();
}
}
Then in your Global.Asax Application_Startup, you can initialize it:
然后在你的全球。Asax Application_Startup,您可以初始化它:
protected void Application_Start()
{
NHibernateSessionManager.Instance.Initialize();
}
#3
11
Avoid and/or minimize the Select N + 1 problem by recognizing when to switch from lazy loading to eager fetching for slow performing queries.
通过识别何时从延迟加载切换到执行缓慢的查询的快速抓取来避免和/或最小化Select N + 1问题。
#4
10
No a recommendation but a tool to help you : NH Prof ( http://nhprof.com/ ) seems to be promising, it can evaluate your use of the ORM framework. It can be a good starting point for your tunning of NHibernate.
没有建议,但是可以帮助您的工具:NH教授(http://nhprof.com/)似乎很有希望,它可以评估您对ORM框架的使用。这可能是您调整NHibernate的一个很好的起点。
#5
4
Without any specifics about the kinds of performance issues you're seeing, I can only offer a generalization: In my experience, most database query performance issues arise from lack of proper indices. So my suggestion for a first action would be to check your query plans for non-indexed queries.
如果没有关于您所看到的性能问题的任何细节,我只能提供一个概括:在我的经验中,大多数数据库查询性能问题都是由于缺乏适当的索引引起的。因此,我的建议是,首先检查查询计划中的非索引查询。
#6
3
NHibernate generates pretty fast SQL right out of the box. I've been using it for a year, and have yet to have to write bare SQL with it. All of my performance problems have been from Normalization and lack of indexes.
NHibernate从这个框中生成非常快的SQL。我已经使用它一年了,还没有使用它编写纯SQL。我所有的性能问题都来自于标准化和索引的缺乏。
The easiest fix is to examine the execution plans of your queries and create proper indexes, especially on your foreign key columns. If you are using Microsoft SQL Server, the "Database Engine Tuning Advisor" helps out a lot with this.
最简单的解决方法是检查查询的执行计划并创建适当的索引,特别是在您的外键列上。如果您正在使用Microsoft SQL Server,“数据库引擎优化顾问”将在这方面提供很多帮助。
#7
3
"One recommendation per answer" only? Then I would go for this one:
“每个答案只推荐一个”?然后我会选这个:
Avoid join duplicates (AKA cartesian products) due to joins along two or more parallel to-many associations; use Exists-subqueries, MultiQueries or FetchMode "subselect" instead.
避免连接重复(又称笛卡尔积),因为连接沿着两个或多个与多个关联并行的连接;使用现有的子查询、多查询或FetchMode“子选择”。
Taken from: Hibernate Performance Tuning Tips
取自:Hibernate性能调优提示。
#8
1
I am only allowed to limit my answer to one option? In that case I would select that you implement the second-level cache mechanism of NHibernate.
我只能回答一个问题?在这种情况下,我将选择您实现NHibernate的二级缓存机制。
This way, for each object in your mapping file you are able to define the cache-strategy. The secondlevel cache will keep already retrieved objects in memory and therefore not make another roundtrip to the database. This is a huge performance booster.
这样,您就可以为映射文件中的每个对象定义缓存策略。secondlevel缓存将保存已经在内存中检索的对象,因此不会对数据库进行另一次往返。这是一个巨大的性能助推器。
Your goal is to define the objects that are constantly accessed by your application. Among those will be general settings and the like.
您的目标是定义应用程序经常访问的对象。其中包括一般的设置等等。
There is plenty of information to be found for nhibernate second level cache and how to implement it.
有很多关于nhibernate二级缓存的信息,以及如何实现它。
Good luck :)
祝你好运:)
#9
1
Caching, Caching, Caching -- Are you using your first level caching correctly [closing sessions prematurely, or using StatelessSession to bypass first level caching]? Do you need to set up a simple second level cache for values that change infrequently? Can you cache query result sets to speed up queries that change infrequently?
缓存、缓存、缓存——您是正确地使用第一级缓存(提前关闭会话,还是使用无状态会话绕过一级缓存)?是否需要为不经常更改的值设置一个简单的二级缓存?您是否可以缓存查询结果集,以加速不经常更改的查询?
[Also configuration -- can you set items as immutable? Can you restructure queries to bring back only the information you need and transform them into the original entity? Will Batman be able to stop the Riddler before he gets to the dam? ... oh, sorry got carried away.]
[还有配置——能否将项目设置为不可变的?您是否可以重组查询以只返回所需的信息并将其转换为原始实体?蝙蝠侠能在他到达大坝前阻止他吗?…哦,对不起太过分了。
#10
1
Profiling is the first step - even simple timed unit tests - to find out where the greatest gains can be made
分析是第一步——即使是简单的定时单元测试——来找出最大的收获
For collections consider setting the batch size to reduce the number of select statements issued - see section Improving performance for details
对于集合,请考虑设置批处理大小以减少发出的select语句的数量——有关细节,请参阅提高性能的部分
#11
1
If you're not already using lazy loading (appropriately), start. Fetching collections when you don't need them is a waste of everything.
如果您还没有使用延迟加载(适当地),请开始。在不需要集合的时候取回集合,是对所有东西的浪费。
Chapter Improving performance describes this and other ways to improve performance.
改进性能一章描述了改进性能的方法。
#12
0
What lotsoffreetime said.
lotsoffreetime所说的。
Read Chapter 19 of the documentation, "Improving Performance".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.html
Hibernate: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
阅读文档的第19章,“提高性能”。NHibernate:http://nhibernate.info/doc/nhibernate-reference/performance.html Hibernate:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
Use SQL Profiler (or equivalent for the database you're using) to locate long-running queries. Optimize those queries with appropriate indexes.
使用SQL Profiler(或您正在使用的数据库的等效文件)定位长时间运行的查询。使用适当的索引优化这些查询。
For database calls used on nearly every single page of an application, use CreateMultiQuery to return multiple resultsets from a single database query.
对于几乎在应用程序的每个页面上使用的数据库调用,可以使用CreateMultiQuery从单个数据库查询返回多个结果集。
And of course, cache. The OutputCache directive for pages/controls. NHibernate caching for data.
当然,缓存。页面/控件的OutputCache指令。NHibernate缓存数据。
#1
49
The first and most dramatic performance problem that you can run into with NHibernate is if you are creating a new session factory for every session you create. Only one session factory instance should be created for each application execution and all sessions should be created by that factory.
NHibernate遇到的第一个、也是最引人注目的性能问题是,如果为创建的每个会话创建一个新的会话工厂。应该为每个应用程序执行创建一个会话工厂实例,并且该工厂应该创建所有会话。
Along those lines, you should continue using the same session as long as it makes sense. This will vary by application, but for most web applications, a single session per request is recommended. If you throw away your session frequently, you aren't gaining the benefits of its cache. Intelligently using the session cache can change a routine with a linear (or worse) number of queries to a constant number without much work.
沿着这些思路,您应该继续使用相同的会话,只要它有意义。这因应用程序而异,但对于大多数web应用程序,建议每个请求使用一个会话。如果你经常丢弃你的会话,你就得不到它缓存的好处。智能地使用会话缓存可以在没有大量工作的情况下,用线性(或更糟)的查询数来改变一个例程。
Equally important is that you want to make sure that you are lazy loading your object references. If you are not, entire object graphs could be loaded for even the most simple queries. There are only certain reasons not to do this, but it is always better to start with lazy loading and switch back as needed.
同样重要的是,您要确保延迟加载对象引用。如果不是,那么即使是最简单的查询也可以加载整个对象图。不这样做是有一定原因的,但是最好从延迟加载开始,然后根据需要进行切换。
That brings us to eager fetching, the opposite of lazy loading. While traversing object hierarchies or looping through collections, it can be easy to lose track of how many queries you are making and you end up with an exponential number of queries. Eager fetching can be done on a per query basis with a FETCH JOIN. In rare circumstances, such as if there is a particular pair of tables you always fetch join, consider turning off lazy loading for that relationship.
这就带来了渴望取回,与惰性装载相反。在遍历对象层次结构或遍历集合时,很容易丢失正在进行的查询的数量,最终得到的查询数量是指数级的。在每个查询基础上都可以使用FETCH JOIN来完成热切的抓取。在很少的情况下,例如如果您总是获取join,那么可以考虑为该关系关闭惰性加载。
As always, SQL Profiler is a great way to find queries that are running slow or being made repeatedly. At my last job we had a development feature that counted queries per page request as well. A high number of queries for a routine is the most obvious indicator that your routine is not working well with NHibernate. If the number of queries per routine or request looks good, you are probably down to database tuning; making sure you have enough memory to store execution plans and data in the cache, correctly indexing your data, etc.
一如既往,SQL Profiler是查找运行缓慢或重复执行的查询的好方法。在我的上一份工作中,我们有一个开发特性,可以计算每个页面请求的查询数。对一个例程的大量查询是表明您的例程在NHibernate中不能正常工作的最明显的标志。如果每个例程或请求的查询数量看起来不错,那么您可能需要对数据库进行调优;确保您有足够的内存来在缓存中存储执行计划和数据,正确地索引数据等等。
One tricky little problem we ran into was with SetParameterList(). The function allows you to easily pass a list of parameters to a query. NHibernate implemented this by creating one parameter for each item passed in. This results in a different query plan for every number of parameters. Our execution plans were almost always getting released from the cache. Also, numerous parameters can significantly slow down a query. We did a custom hack of NHibernate to send the items as a delimited list in a single parameter. The list was separated in SQL Server by a table value function that our hack automatically inserted into the IN clause of the query. There could be other land mines like this depending on your application. SQL Profiler is the best way to find them.
我们遇到的一个棘手的小问题是SetParameterList()。该函数允许您轻松地将参数列表传递给查询。NHibernate通过为传入的每个项创建一个参数来实现这一点。这将导致对每个参数的不同查询计划。我们的执行计划几乎总是从缓存中释放出来。此外,许多参数可以显著降低查询速度。我们对NHibernate做了一个定制的修改,将项目作为带分隔符的列表发送到一个参数中。在SQL Server中,列表被一个表值函数分隔,我们的hack将这个表值函数自动插入到查询的in子句中。根据您的应用,可能还有其他类似的地雷。SQL分析器是找到它们的最佳方法。
#2
25
NHibernate's SessionFactory is an expensive operation so a good strategy is to creates a Singleton which ensures that there is only ONE instance of SessionFactory in memory:
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();
}
}
Then in your Global.Asax Application_Startup, you can initialize it:
然后在你的全球。Asax Application_Startup,您可以初始化它:
protected void Application_Start()
{
NHibernateSessionManager.Instance.Initialize();
}
#3
11
Avoid and/or minimize the Select N + 1 problem by recognizing when to switch from lazy loading to eager fetching for slow performing queries.
通过识别何时从延迟加载切换到执行缓慢的查询的快速抓取来避免和/或最小化Select N + 1问题。
#4
10
No a recommendation but a tool to help you : NH Prof ( http://nhprof.com/ ) seems to be promising, it can evaluate your use of the ORM framework. It can be a good starting point for your tunning of NHibernate.
没有建议,但是可以帮助您的工具:NH教授(http://nhprof.com/)似乎很有希望,它可以评估您对ORM框架的使用。这可能是您调整NHibernate的一个很好的起点。
#5
4
Without any specifics about the kinds of performance issues you're seeing, I can only offer a generalization: In my experience, most database query performance issues arise from lack of proper indices. So my suggestion for a first action would be to check your query plans for non-indexed queries.
如果没有关于您所看到的性能问题的任何细节,我只能提供一个概括:在我的经验中,大多数数据库查询性能问题都是由于缺乏适当的索引引起的。因此,我的建议是,首先检查查询计划中的非索引查询。
#6
3
NHibernate generates pretty fast SQL right out of the box. I've been using it for a year, and have yet to have to write bare SQL with it. All of my performance problems have been from Normalization and lack of indexes.
NHibernate从这个框中生成非常快的SQL。我已经使用它一年了,还没有使用它编写纯SQL。我所有的性能问题都来自于标准化和索引的缺乏。
The easiest fix is to examine the execution plans of your queries and create proper indexes, especially on your foreign key columns. If you are using Microsoft SQL Server, the "Database Engine Tuning Advisor" helps out a lot with this.
最简单的解决方法是检查查询的执行计划并创建适当的索引,特别是在您的外键列上。如果您正在使用Microsoft SQL Server,“数据库引擎优化顾问”将在这方面提供很多帮助。
#7
3
"One recommendation per answer" only? Then I would go for this one:
“每个答案只推荐一个”?然后我会选这个:
Avoid join duplicates (AKA cartesian products) due to joins along two or more parallel to-many associations; use Exists-subqueries, MultiQueries or FetchMode "subselect" instead.
避免连接重复(又称笛卡尔积),因为连接沿着两个或多个与多个关联并行的连接;使用现有的子查询、多查询或FetchMode“子选择”。
Taken from: Hibernate Performance Tuning Tips
取自:Hibernate性能调优提示。
#8
1
I am only allowed to limit my answer to one option? In that case I would select that you implement the second-level cache mechanism of NHibernate.
我只能回答一个问题?在这种情况下,我将选择您实现NHibernate的二级缓存机制。
This way, for each object in your mapping file you are able to define the cache-strategy. The secondlevel cache will keep already retrieved objects in memory and therefore not make another roundtrip to the database. This is a huge performance booster.
这样,您就可以为映射文件中的每个对象定义缓存策略。secondlevel缓存将保存已经在内存中检索的对象,因此不会对数据库进行另一次往返。这是一个巨大的性能助推器。
Your goal is to define the objects that are constantly accessed by your application. Among those will be general settings and the like.
您的目标是定义应用程序经常访问的对象。其中包括一般的设置等等。
There is plenty of information to be found for nhibernate second level cache and how to implement it.
有很多关于nhibernate二级缓存的信息,以及如何实现它。
Good luck :)
祝你好运:)
#9
1
Caching, Caching, Caching -- Are you using your first level caching correctly [closing sessions prematurely, or using StatelessSession to bypass first level caching]? Do you need to set up a simple second level cache for values that change infrequently? Can you cache query result sets to speed up queries that change infrequently?
缓存、缓存、缓存——您是正确地使用第一级缓存(提前关闭会话,还是使用无状态会话绕过一级缓存)?是否需要为不经常更改的值设置一个简单的二级缓存?您是否可以缓存查询结果集,以加速不经常更改的查询?
[Also configuration -- can you set items as immutable? Can you restructure queries to bring back only the information you need and transform them into the original entity? Will Batman be able to stop the Riddler before he gets to the dam? ... oh, sorry got carried away.]
[还有配置——能否将项目设置为不可变的?您是否可以重组查询以只返回所需的信息并将其转换为原始实体?蝙蝠侠能在他到达大坝前阻止他吗?…哦,对不起太过分了。
#10
1
Profiling is the first step - even simple timed unit tests - to find out where the greatest gains can be made
分析是第一步——即使是简单的定时单元测试——来找出最大的收获
For collections consider setting the batch size to reduce the number of select statements issued - see section Improving performance for details
对于集合,请考虑设置批处理大小以减少发出的select语句的数量——有关细节,请参阅提高性能的部分
#11
1
If you're not already using lazy loading (appropriately), start. Fetching collections when you don't need them is a waste of everything.
如果您还没有使用延迟加载(适当地),请开始。在不需要集合的时候取回集合,是对所有东西的浪费。
Chapter Improving performance describes this and other ways to improve performance.
改进性能一章描述了改进性能的方法。
#12
0
What lotsoffreetime said.
lotsoffreetime所说的。
Read Chapter 19 of the documentation, "Improving Performance".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.html
Hibernate: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
阅读文档的第19章,“提高性能”。NHibernate:http://nhibernate.info/doc/nhibernate-reference/performance.html Hibernate:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
Use SQL Profiler (or equivalent for the database you're using) to locate long-running queries. Optimize those queries with appropriate indexes.
使用SQL Profiler(或您正在使用的数据库的等效文件)定位长时间运行的查询。使用适当的索引优化这些查询。
For database calls used on nearly every single page of an application, use CreateMultiQuery to return multiple resultsets from a single database query.
对于几乎在应用程序的每个页面上使用的数据库调用,可以使用CreateMultiQuery从单个数据库查询返回多个结果集。
And of course, cache. The OutputCache directive for pages/controls. NHibernate caching for data.
当然,缓存。页面/控件的OutputCache指令。NHibernate缓存数据。