Hibernate MUUUUUITO lento a ponto de ficar impossível de usar!

Salve GUJ, estou enfrentando um problema com o Hibernate que está me tirando as noites de sono… será que alguem pode me ajudar?

Eu tenho uma tabela de Notas Fiscais que tem 15 colunas e 1 milhão de registros, vejam o tempo que leva para obter SÓ um registro desta tabela com JDBC e com HIBERNATE.

JDBC:

String sql = "Select * From NF Where nfid > 0 And nfempresa  = 4 Order By nfid asc limit 1";
double t1 = System.currentTimeMillis();
ResultSet rs = DBUtil.getConnection().prepareStatement(sql).executeQuery();
System.out.println("Tempo para RS em SQL " + (System.currentTimeMillis()-t1));

HIBERNATE:

String hql = "From NF nf where nf.nfid > 0 And nf.empresa.empresaid = 4 Order By nf.nfid asc";
t1 = System.currentTimeMillis();
Session s = DBUtil.openSession();
Query q = s.createQuery(hql);
q.setMaxResults(1);
q.uniqueResult();
System.out.println("Tempo para obter objeto em HQL " + (System.currentTimeMillis()-t1));

resultado:

Tempo para RS em SQL 150.0
Tempo para obter objeto em HQL 7611.0

O detalhe é que quando a tabela tem poucos registros dai o tempo do Hibernate até fica aceitavel assim está parecendo que o “setMaxResult(1)” não está servindo pra nada.

Alguém sabe como resolver isso se é que tem solução usando o hibernate?

Qual a query que o Hibernate gera?
Seu BD tem índices?

Gera a seguinte sql

"TODOS OS CAPOS DA TABELA" + from nf nfx0_ where nfx0_.nfid>0 and nfx0_.nfempresa=4 order by nfx0_.nfid asc limit ?

Tem um indice PK no nfid

danieldestro Você também está achando este tempo estranho certo?
Porque o meu problema é se esse tem alguma coisa errada no meu sistema que está demorando assim eu até fico mais tranquilo e vou procurar o problema mas se o Hibernate realmente leva esse tempo e não há nada que possa ser feito para aproximar o hibernate do tempo do JDBC ai sim eu vou estar com um gigantesco problema pois vou ter que tirar o Hibernate do sistema e passar tudo pra JDBC…

Rafael, o que “DBUtil.openSession()” faz?

Você não tá criando a SessionFactory nele né?

Não, não a SessionFactory só é criada na inicialização do sistema mesmo

[quote=rafaelbtz][quote]
Rafael, o que “DBUtil.openSession()” faz?
Você não tá criando a SessionFactory nele né?
[/quote]
Não, não a SessionFactory só é criada na inicialização do sistema mesmo[/quote]

Ta, mas o que ele faz?

Amigo creio que este tempo em que você está considerando está incluido o tempo pra carregar o Hibernate, seu arquivo de configuração, mapeamentos, etc. Você deveria pegar apenas o tempo de execução da query.

Quando você faz:

Session s = DBUtil.openSession();

A Session Factory está sendo criada ai se é a primeira vez que seu teste usa o Hibernate. Me corrijam se eu estiver errado.

[]'s

Além do que o pessoal já falou, sua comparação é falha. Você tem que, no mínimo, fazer rs.next() e ler todos os campos contidos no registro para que ela seja justa, inclusive convertendo para o tipo de dados que o seu bean contém.

O DBUtil faz o seguinte:

	public static Session openSession(){
		return sessionFactory.openSession();
	}

Ele não cria a SessionFactory e nem o Configuration nem nada…

Mas eu descobri que se eu tirar o “nf.empresa.empresaid = 4” da HQL ele retorna a consulta no tempo que deveria ser mesmo 188 milis, o mapeamento desta ForenKey no HBM é o seguinte

     <many-to-one
        name="empresa"
        class="a.cas.modelo.Empresa"
        not-null="true"
    >
        <column name="empresa" />
    </many-to-one>

e no banco de dados este campo empresa da tabela NF aponta para o campo empresaId da tabela Empresa. Alguem sabe o que pode estar acontecendo porque aparentemente não tem nada de errado

Olá,

Voce ja viu qual SQL o hibernate ta gerando?
Outra coisa pelo que entendi tu tens um relacionamento no mapeamento da tabela NF correto? Este relacionamento esta com LAZY=TRUE ?

]['s

A SQL que ele está gerando está logo acima mas na parte que refere a FK ele gera “nfx0_.nfempresa=4” o que está correto

Sim na tabela NF eu tenho um relacionamento Many-To-One, já tabela empresa eu não tenho um Set relacionamento One-To-Many pois eu só uso o Many-To-One da tabela NF não me importa o One-To-Many na tabela Empresa, será que isso pode afetar em alguma coisa??? ter um Many-To-One sem um One-To-Many na outra ponta do relacionamento

[quote=rafaelbtz]Sim na tabela NF eu tenho um relacionamento Many-To-One, já tabela empresa eu não tenho um Set relacionamento One-To-Many pois eu só uso o Many-To-One da tabela NF não me importa o One-To-Many na tabela Empresa, será que isso pode afetar em alguma coisa??? ter um Many-To-One sem um One-To-Many na outra ponta do relacionamento
[/quote]

Nao. O que pode estar ocorrendo é o seguinte. Tu tem um relacionamento da classe NF para Empresa e se a classe Empresa tiver relacionamento em cascata com outras classes e no mapeamento tudo estiver como LAZY=FALSE isso é problema pois o Hibernate estará carregando alem dos dados da NF os dados dos relacionamentos.

Quando tu gera a consulta la onde ele mostra o SQL que ele faz na tabela NF ele nao faz em outras tabelas tb?

Faz um teste basico, tira o relacionamento da NF para Empresa e ve se melhora. Se der diferenca tem que ver os mapeamentos dos relacionamentos pq o problema é ali.

]['s

execute o mesmo teste várias vezes.

Apenas uma vez não é o suficiente para se concluir algo…
O ambiente [pc, so, etc] influencia no tempo consideralmente x[

Ao longo destes 5 anos já deve ter executado muuuuuuuitas vezes!

Ao longo destes 5 anos já deve ter executado muuuuuuuitas vezes![/quote]

depois que eu vi que o tópico era antigo…
Deu preguiça de editar/excluir…
kkkkkkkkkkkk

Mas é até bom, se alguem cair aqui como eu caí,
as vezes pode ajudar alguém x]

abrazz ae
[PS: faltou aquela carta: tópico que renasce, já viu?]