Programing

NHibernate의 성능을 향상시키는 가장 좋은 방법은 무엇입니까?

crosscheck 2020. 12. 1. 07:42
반응형

NHibernate의 성능을 향상시키는 가장 좋은 방법은 무엇입니까?


NHibernate를 ORM으로 사용하는 응용 프로그램이 있으며 때로는 데이터가 액세스되는 방식으로 인해 성능 문제가 발생합니다. NHibernate의 성능을 향상시키기 위해 어떤 일을 할 수 있습니까? (답변 당 하나의 추천으로 제한하세요)


NHibernate에서 발생할 수있는 첫 번째이자 가장 극적인 성능 문제는 생성하는 모든 세션에 대해 새로운 세션 팩토리를 생성하는 경우입니다. 각 응용 프로그램 실행에 대해 하나의 세션 팩토리 인스턴스 만 만들어야하며 모든 세션은 해당 팩토리에서 만들어야합니다.

그 라인을 따라, 당신은 의미가있는 한 동일한 세션을 계속 사용해야합니다. 이는 애플리케이션에 따라 다르지만 대부분의 웹 애플리케이션의 경우 요청 당 단일 세션이 권장됩니다. 세션을 자주 버리면 캐시의 이점을 얻지 못합니다. 세션 캐시를 지능적으로 사용하면 많은 작업없이 선형 (또는 더 나쁜) 수의 쿼리가있는 루틴을 상수로 변경할 수 있습니다.

똑같이 중요한 것은 개체 참조를 지연로드하고 있는지 확인하는 것입니다. 그렇지 않은 경우 가장 간단한 쿼리에서도 전체 개체 그래프를로드 할 수 있습니다. 이를 수행하지 않는 특정 이유가 있지만 항상 지연로드로 시작하고 필요에 따라 다시 전환하는 것이 좋습니다.

이는 지연 로딩의 반대 인 eager fetching으로 이어집니다. 개체 계층 구조를 탐색하거나 컬렉션을 반복하는 동안 작성중인 쿼리 수를 추적하지 못해 기하 급수적 인 쿼리 수로 끝날 수 있습니다. Eager fetching은 FETCH JOIN을 사용하여 쿼리별로 수행 할 수 있습니다. 항상 조인을 가져 오는 특정 테이블 쌍이있는 경우와 같은 드문 경우에는 해당 관계에 대해 지연로드를 해제하는 것이 좋습니다.

항상 그렇듯이 SQL 프로필러는 느리게 실행되거나 반복적으로 생성되는 쿼리를 찾는 좋은 방법입니다. 마지막 작업에서 페이지 요청 당 쿼리를 계산하는 개발 기능도있었습니다. 루틴에 대한 쿼리 수가 많으면 루틴이 NHibernate에서 제대로 작동하지 않는다는 가장 분명한 표시기입니다. 루틴 또는 요청 당 쿼리 수가 양호 해 보인다면 아마도 데이터베이스 튜닝에 속했을 것입니다. 실행 계획과 데이터를 캐시에 저장하고 데이터를 올바르게 인덱싱 할 수있는 충분한 메모리가 있는지 확인합니다.

우리가 만난 까다로운 작은 문제 중 하나는 SetParameterList ()입니다. 이 함수를 사용하면 매개 변수 목록을 쿼리에 쉽게 전달할 수 있습니다. NHibernate는 전달 된 각 항목에 대해 하나의 매개 변수를 생성하여이를 구현했습니다. 이는 매개 변수 수마다 다른 쿼리 계획을 생성합니다. 우리의 실행 계획은 거의 항상 캐시에서 해제되었습니다. 또한 수많은 매개 변수로 인해 쿼리 속도가 크게 저하 될 수 있습니다. 항목을 단일 매개 변수로 구분 된 목록으로 보내기 위해 NHibernate의 사용자 정의 해킹을 수행했습니다. 목록은 SQL Server에서 우리 해킹이 쿼리의 IN 절에 자동으로 삽입 한 테이블 값 함수로 구분되었습니다. 응용 프로그램에 따라 이와 같은 다른 지뢰가있을 수 있습니다. SQL 프로파일 러는이를 찾는 가장 좋은 방법입니다.


NHibernate의 SessionFactory는 비용이 많이 드는 작업이므로 메모리에 SessionFactory 인스턴스가 하나만 있는지 확인하는 Singleton을 만드는 것이 좋은 전략입니다.

   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();
}

느리게 실행되는 쿼리를 위해 지연로드에서 즉시 가져 오기로 전환 할시기를 인식 하여 Select N + 1 문제방지 및 / 또는 최소화 합니다.


권장 사항은 아니지만 도움이되는 도구 : NH Prof ( http://nhprof.com/ )는 유망한 것 같습니다. ORM 프레임 워크 사용을 평가할 수 있습니다. NHibernate를 조정하기위한 좋은 시작점이 될 수 있습니다.


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.


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.

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.


"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.

Taken from: Hibernate Performance Tuning Tips


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.

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.

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.

Good luck :)


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.]


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


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.


What lotsoffreetime said.

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

Use SQL Profiler (or equivalent for the database you're using) to locate long-running queries. Optimize those queries with appropriate indexes.

For database calls used on nearly every single page of an application, use CreateMultiQuery to return multiple resultsets from a single database query.

And of course, cache. The OutputCache directive for pages/controls. NHibernate caching for data.

참고URL : https://stackoverflow.com/questions/67103/what-is-the-best-way-to-improve-performance-of-nhibernate

반응형