문제

NHibernate를 ORM으로 사용하는 애플리케이션이 있는데 때로는 데이터에 액세스하는 방식으로 인해 성능 문제가 발생합니다.NHibernate의 성능을 향상시키기 위해 어떤 종류의 작업을 수행할 수 있습니까?(답변 당 하나의 추천으로 제한하십시오)

도움이 되었습니까?

해결책

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

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

마찬가지로 중요한 것은 객체 참조를 지연 로딩하고 있는지 확인하는 것입니다.그렇지 않은 경우 가장 간단한 쿼리에도 전체 개체 그래프가 로드될 수 있습니다.이렇게 하지 않는 데는 몇 가지 이유가 있지만 지연 로딩으로 시작하고 필요에 따라 다시 전환하는 것이 항상 더 좋습니다.

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

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

우리가 직면한 한 가지 까다롭고 작은 문제는 SetParameterList()와 관련된 것이었습니다.이 기능을 사용하면 매개변수 목록을 쿼리에 쉽게 전달할 수 있습니다.NHibernate는 전달된 각 항목에 대해 하나의 매개변수를 생성하여 이를 구현했습니다.이로 인해 모든 매개변수 수에 대해 서로 다른 쿼리 계획이 생성됩니다.우리의 실행 계획은 거의 항상 캐시에서 해제되었습니다.또한 매개변수가 너무 많으면 쿼리 속도가 크게 느려질 수 있습니다.우리는 항목을 단일 매개변수로 구분된 목록으로 보내기 위해 NHibernate의 사용자 정의 해킹을 수행했습니다.이 목록은 해킹이 쿼리의 IN 절에 자동으로 삽입한 테이블 값 함수에 의해 SQL Server에서 분리되었습니다.귀하의 용도에 따라 이와 같은 다른 지뢰가 있을 수도 있습니다.SQL 프로파일러는 이를 찾는 가장 좋은 방법입니다.

다른 팁

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

방지 및/또는 최소화 N + 1 문제 선택 수행 속도가 느린 쿼리에 대해 지연 로딩에서 즉시 가져오기로 전환해야 하는 시기를 인식함으로써 가능합니다.

권장 사항은 아니지만 도움이 되는 도구입니다.NH 교수 ( http://nhprof.com/ ) 유망한 것으로 보이며 ORM 프레임워크 사용을 평가할 수 있습니다.이는 NHibernate 튜닝을 위한 좋은 출발점이 될 수 있습니다.

현재 보고 있는 성능 문제의 종류에 대해 구체적인 설명 없이 일반화만 제안할 수 있습니다.내 경험에 따르면 대부분의 데이터베이스 쿼리 성능 문제는 적절한 인덱스가 부족하여 발생합니다.따라서 첫 번째 작업에 대한 제안은 인덱싱되지 않은 쿼리에 대한 쿼리 계획을 확인하는 것입니다.

NHibernate는 즉시 사용 가능한 매우 빠른 SQL을 생성합니다.나는 그것을 1년 동안 사용해왔지만 아직 그것으로 SQL을 직접 작성해 본 적이 없습니다.내 모든 성능 문제는 다음에서 비롯되었습니다. 표준화 그리고 인덱스가 부족합니다.

가장 쉬운 해결 방법은 쿼리 실행 계획을 검사하고 특히 외래 키 열에 적절한 인덱스를 만드는 것입니다.Microsoft SQL Server를 사용하는 경우 "데이터베이스 엔진 튜닝 관리자"가 많은 도움이 됩니다.

"답변당 하나의 추천"만 가능합니까?그렇다면 나는 이것으로 갈 것입니다 :

둘 이상의 병렬 대다 연관에 따른 조인으로 인한 조인 중복(일명 데카르트 곱)을 피하십시오.대신 Exists-subqueries, MultiQueries 또는 FetchMode "subselect"를 사용하세요.

출처: 최대 절전 모드 성능 조정 팁

답변을 한 가지 옵션으로만 제한할 수 있습니까?그런 경우에는 NHibernate의 두 번째 수준 캐시 메커니즘을 구현하도록 선택하겠습니다.

이렇게 하면 매핑 파일의 각 개체에 대해 캐시 전략을 정의할 수 있습니다.두 번째 수준 캐시는 이미 검색된 개체를 메모리에 유지하므로 데이터베이스로 다시 왕복하지 않습니다.이것은 엄청난 성능 향상입니다.

여러분의 목표는 애플리케이션에서 지속적으로 액세스하는 객체를 정의하는 것입니다.그 중에는 일반 설정 등이 있습니다.

nhibernate 두 번째 수준 캐시와 이를 구현하는 방법에 대해 찾을 수 있는 정보가 많이 있습니다.

행운을 빌어요 :)

캐싱, 캐싱, 캐싱 - 첫 번째 수준 캐싱을 올바르게 사용하고 있습니까[세션을 조기에 닫거나 StatelessSession을 사용하여 첫 번째 수준 캐싱을 우회]하고 있습니까?자주 변경되지 않는 값에 대해 간단한 두 번째 수준 캐시를 설정해야 합니까?자주 변경되지 않는 쿼리의 속도를 높이기 위해 쿼리 결과 집합을 캐시할 수 있습니까?

[또한 구성 - 항목을 변경할 수 없도록 설정할 수 있나요?필요한 정보만 다시 가져오고 이를 원래 엔터티로 변환하도록 쿼리를 재구성할 수 있습니까?배트맨은 리들러가 댐에 도착하기 전에 그를 막을 수 있을까요?...아, 미안, 너무 끌려갔어.]

프로파일링은 가장 큰 이득을 얻을 수 있는 위치를 찾기 위한 첫 번째 단계입니다. 간단한 시간 단위 테스트라도 가능합니다.

컬렉션의 경우 발행된 select 문 수를 줄이기 위해 배치 크기 설정을 고려하세요. 섹션을 참조하세요. 성능 향상 자세한 내용은

아직 지연 로딩을 (적절하게) 사용하고 있지 않다면 시작하세요.필요하지 않을 때 컬렉션을 가져오는 것은 모든 것을 낭비하는 것입니다.

장 성능 향상 성능을 향상시키는 방법과 기타 방법을 설명합니다.

lotoffreetime이 말한 것.

"성능 개선" 문서의 19장을 읽어보세요.
NH절전 모드: http://nhibernate.info/doc/nhibernate-reference/performance.html
최대 절전 모드: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

장기 실행 쿼리를 찾으려면 SQL 프로파일러(또는 사용 중인 데이터베이스에 해당하는 기능)를 사용하세요.적절한 인덱스를 사용하여 해당 쿼리를 최적화하십시오.

애플리케이션의 거의 모든 단일 페이지에서 사용되는 데이터베이스 호출의 경우 CreateMultiQuery를 사용하여 단일 데이터베이스 쿼리에서 여러 결과 집합을 반환합니다.

물론 캐시도 마찬가지입니다.페이지/컨트롤에 대한 OutputCache 지시문입니다.데이터를 위한 NHibernate 캐싱.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top