it-swarm-pt.tech

Qual é a melhor maneira de melhorar o desempenho do NHibernate?

Eu tenho um aplicativo que usa o NHibernate como ORM e, às vezes, apresenta problemas de desempenho devido à maneira como os dados estão sendo acessados ​​por ele. Que tipo de ação pode ser feita para melhorar o desempenho do NHibernate? (Limite a uma recomendação por resposta)

61
Ray Vega

O primeiro e mais dramático problema de desempenho que você pode encontrar com o NHibernate é se estiver criando uma nova fábrica de sessões para cada sessão que criar. Somente uma instância de factory de sessão deve ser criada para cada execução do aplicativo e todas as sessões devem ser criadas por esse factory.

Nesse sentido, você deve continuar usando a mesma sessão, desde que faça sentido. Isso varia de acordo com o aplicativo, mas para a maioria dos aplicativos Web, é recomendável uma única sessão por solicitação. Se você joga fora sua sessão com frequência, não está obtendo os benefícios de seu cache. O uso inteligente do cache da sessão pode alterar uma rotina com um número linear (ou pior) de consultas para um número constante sem muito trabalho.

Igualmente importante é que você quer ter certeza de que está carregando preguiçosamente suas referências de objeto. Caso contrário, gráficos de objetos inteiros podem ser carregados até para as consultas mais simples. Existem apenas alguns motivos para não fazer isso, mas é sempre melhor começar com um carregamento lento e voltar quando necessário.

Isso nos leva à busca ansiosa, o oposto do carregamento preguiçoso. Ao percorrer hierarquias de objetos ou percorrer coleções, pode ser fácil perder o controle de quantas consultas você está fazendo e você acaba com um número exponencial de consultas. A busca ansiosa pode ser feita por consulta com um FETCH JOIN. Em circunstâncias raras, como se houver sempre um determinado par de tabelas em que você busca a junção, considere desativar o carregamento lento para esse relacionamento.

Como sempre, o SQL Profiler é uma ótima maneira de encontrar consultas que estão executando lentamente ou sendo feitas repetidamente. No meu último trabalho, tínhamos um recurso de desenvolvimento que também contava consultas por solicitação de página. Um número alto de consultas para uma rotina é o indicador mais óbvio de que sua rotina não está funcionando bem com o NHibernate. Se o número de consultas por rotina ou solicitação parecer bom, você provavelmente está no ajuste do banco de dados; verifique se você possui memória suficiente para armazenar planos e dados de execução no cache, indexar corretamente seus dados etc.

Um pequeno problema complicado que encontramos foi com SetParameterList (). A função permite que você passe facilmente uma lista de parâmetros para uma consulta. O NHibernate implementou isso criando um parâmetro para cada item passado. Isso resulta em um plano de consulta diferente para cada número de parâmetros. Nossos planos de execução quase sempre eram liberados do cache. Além disso, vários parâmetros podem retardar significativamente uma consulta. Fizemos um hack personalizado do NHibernate para enviar os itens como uma lista delimitada em um único parâmetro. A lista foi separada no SQL Server por uma função de valor de tabela que nosso hack inseriu automaticamente na cláusula IN da consulta. Pode haver outras minas terrestres como essa, dependendo da sua aplicação. O SQL Profiler é a melhor maneira de encontrá-los.

53
Chuck

O SessionFactory do NHibernate é uma operação cara, portanto, uma boa estratégia é criar um Singleton que garanta que haja apenas UMA instância do SessionFactory na memória:

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

Em seu Global.Asax Application_Startup, você pode inicializá-lo:

protected void Application_Start()
{
    NHibernateSessionManager.Instance.Initialize();
}
26
David P

Evite e/ou minimize o Selecione o problema N + 1 reconhecendo quando alternar do carregamento lento para a busca ansiosa para consultas de desempenho lento.

11
Ray Vega

Nenhuma recomendação, mas uma ferramenta para ajudá-lo: O NH Prof ( http://nhprof.com/ ) parece ser promissor, ele pode avaliar o uso da estrutura ORM. Pode ser um bom ponto de partida para você tentar o NHibernate.

10
MatthieuGD

Sem detalhes específicos sobre os tipos de problemas de desempenho que você está vendo, só posso oferecer uma generalização: Na minha experiência, a maioria dos problemas de desempenho de consultas ao banco de dados surge da falta de índices adequados. Portanto, minha sugestão para uma primeira ação seria verificar seus planos de consulta para consultas não indexadas.

4
Mike Monette

Apenas uma recomendação por resposta? Então eu iria para este:

Evite junções duplicadas (produtos cartesianos AKA) devido a junções ao longo de duas ou mais associações paralelas a muitas; use Exist-subconsultas, MultiQueries ou FetchMode "subselect".

Retirado de: Hibernate Performance Tuning Tips

3
gnome26

O NHibernate gera SQL muito rápido, pronto para uso. Eu o uso há um ano e ainda tenho que escrever SQL puro com ele. Todos os meus problemas de desempenho foram de Normalização e falta de índices.

A correção mais fácil é examinar os planos de execução de suas consultas e criar índices adequados, especialmente nas colunas de chave estrangeira. Se você estiver usando o Microsoft SQL Server, o "Orientador de Otimização do Mecanismo de Banco de Dados" ajuda muito nisso.

3
Eric Lathrop

Só posso limitar minha resposta a uma opção? Nesse caso, eu selecionaria que você implementasse o mecanismo de cache de segundo nível do NHibernate.

Dessa forma, para cada objeto no seu arquivo de mapeamento, você poderá definir a estratégia de cache. O cache de segundo nível manterá os objetos já recuperados na memória e, portanto, não fará outra ida e volta ao banco de dados. Este é um enorme impulsionador de desempenho.

Seu objetivo é definir os objetos que são constantemente acessados ​​pelo seu aplicativo. Entre esses serão configurações gerais e afins.

Há muitas informações a serem encontradas para o cache de segundo nível nhibernate e como implementá-lo.

Boa sorte :)

1
Hace

A criação de perfil é o primeiro passo - mesmo testes simples de unidade de tempo - para descobrir onde os maiores ganhos podem ser alcançados

Para coleções, considere definir o tamanho do lote para reduzir o número de instruções selecionadas emitidas - consulte a seção Melhorando o desempenho para obter detalhes

1
Richard

Se você ainda não estiver usando o carregamento lento (adequadamente), inicie. Buscar coleções quando você não precisa delas é um desperdício de tudo.

Capítulo Melhorando o desempenho descreve esta e outras maneiras de melhorar o desempenho.

1
lotsoffreetime

Armazenamento em cache, armazenamento em cache, armazenamento em cache - Você está usando o cache de primeiro nível corretamente [fechando as sessões prematuramente ou usando StatelessSession para ignorar o cache de primeiro nível]? Você precisa configurar um cache de segundo nível simples para valores que mudam com pouca frequência? Você pode armazenar em cache conjuntos de resultados de consultas para acelerar consultas que mudam com pouca frequência?

[Também configuração - você pode definir itens como imutáveis? Você pode reestruturar as consultas para recuperar apenas as informações necessárias e transformá-las na entidade original? Batman será capaz de parar o Charada antes que ele chegue à represa? ... oh, desculpe me empolguei.]

1
Watson

O que muitas vezes disse.

Leia o capítulo 19 da documentação, "Melhorando o desempenho".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.html
Hibernate: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Use o SQL Profiler (ou equivalente para o banco de dados que você está usando) para localizar consultas de longa duração. Otimize essas consultas com índices apropriados.

Para chamadas de banco de dados usadas em quase todas as páginas de um aplicativo, use CreateMultiQuery para retornar vários conjuntos de resultados de uma única consulta ao banco de dados.

E, claro, cache. A diretiva OutputCache para páginas/controles. Armazenamento em cache do NHibernate para dados.

0
Axl