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?
"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…
[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]
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.
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.
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
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
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 ?
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.