Estou fazendo uma pesquisa paginada com Hibernate e SQL Server 2000.
a pesquisa funciona mas está absurdamente lenta, para trazer 3 registros, demora 20 segundos.
quando retiro a paginação a pesquisa retorna 100 registros em menos de 1 segundo.
o sql gerado pelo hibernate inclui o predicado top 3, na segunda página top 6 e assim por diante.
alguém teria alguma experiência e/ou sugestão para este tipo de consulta.
Vc ta usando o dialeto correto para o SQLserver ? Outra coisa, em uma consulta paginada o select deve conter a partir de que posição vc deseja e quantos elementos devem ser retornados.
Essa é o metodo generico que faz pesquisa paginada.
public List<PersistentObject> listByJPQLPagination(String JPQL,
Map<String, Object> params, int inicio, int maximo) {
Query query = em.createQuery(JPQL);
if(params != null && !params.isEmpty()){
for (String key : params.keySet()) {
query.setParameter(key, params.get(key));
}
}
query.setFirstResult(inicio);
query.setMaxResults(maximo);
List<PersistentObject> list = query.getResultList();
return list;
}
Esta é a sql gerada pelo hibernate
select
top 3 tabela1Campo1_5_,
tabela1Campo2_5_,
tabela1Campo3_5_,
tabela1Campo9_5_,
tabela1Campo4_5_,
tabela1Campo5_5_,
tabela1Campo6_5_,
tabela1Campo7_5_,
tabela1Campo8_5_
from
tabela1
inner join
tabela2_
on tabela1_codigo=tabela2._codigo
where
tabela1_codigo=1
and tabela2._campo1 =61
and (
tabela2._codigo in (
select
max(tabela2_.faspro_codigo)
from
tabela2_
group by
tabela2_.codigo
)
)
and (
tabela1_codigo in (
select
max(tabela1_.trapro_codigo)
from
tabela1
group by
tabela1.pro_codigo
)
)
order by
tabela2_.data desc
È eu fiz o teste e constatei isso que vc falou.
Vou dá uma pesquisada sobre o top no SQL SERVER, fiz o teste no Banco de desenvolviemtno e de produção e os 2 apresentaram lentidão nesta sql com comando top.
Fiz o teste com o top em outras consultas e realmente é bem rápido.
Nessa consulta que postei é que apresenta lentidao com top, realizando a consulta normal o resultado é instantâneo
kra, nao conheco bem o hibernate, infelizmente, mas pq vc, ao inves de deixa-lo criar a query, nao faz algo assim em hql:
int num_pag; //esta variavel recebe o numero da pagina que se quer acessar
SELECT TOP 3 * FROM sua_tabela WHERE sua_pk NOT IN ( SELECT TOP(3 x num_pag) sua_pk FROM sua_tabela)
neste caso, para num_pag = 1, o select mais de dentro retorna as 3 primeiras linha e o mais de fora, retorna as 3 primeiras linhas apos, assim essa instrucao retorna da 4ª a 6ª linhas.
Já tive que fazer paginação com hibernate e SQL Server, e só digo uma coisa, não faça, hehe
Pq o hibernate vai fazer como o allancmm falou, na primeira pagina ele resgata 10 registros, depois 20, depois 30…entendeu? Ele não pula os 10 primeiros na segunda pagina pra trazer só os outros 10.
A solução aqui na minha empresa foi apelar pra SQLQuery
select t.id from ( select ROW_NUMBER() OVER (PARTITION BY 1 ORDER BY q.ID DESC) as LINHA, q.ID from (
//aqui fica sua query SQL
) q ) t
where LINHA between :inicio and :fim order by t.id desc
Onde inicio é a posição inicial que devemos trazer e fim a posição final.
Se eu quero trazer 10 por pagina eu faço.
inicio = numeroDaPagina x quantidadePorPagina
fim = inicio + quantidadePorPagina
Baseado nisso você pode adaptar melhor a query ao seu caso.
As duas propostas são muito boas. Mas vcs sabem, esta coisa de desenvolvimento ultra-rápido prazos apertados e sobrecarga de trabalho
faz com que nós desenvolvedores, busquemos atalhos para agilizar o Desenvolvimento.
O Hibernate é uma ferramenta fantástica para o desenvolvimento ágio.
Imagine vc criar “querys” “dtos” “vos” e outro “os” a mais em um sistema que faz manutenção em 30, 40 50 tabelas no banco.
No meu caso quando eu terminar de implementar as “query e os” o prazo acabou e não tenho nada a apresentar.
Bom deixando a choradeira para trás, e voltando ao problema.
Manti a consulta, realmente esta consulta com top faz o descrito acima, trás 10, depois 20 e assim por diante.
Para melhorar a consulta, Usamos o SqlManager e executamos o plano de execução da consulta, dessa forma descobrimos os gargalos da consulta.
Então, foi criado indexes nas tabelas envolvidas na consulta.
O Tempo de resposta melhorou consideravelmente, cai dos 20 segundos para 1 segundo.
Não me pergunte como foi feito, não foi eu quem fiz, estava fazendo outras coisa conforme a choradeira rss.
Mas quando tiver um tempo, vou pergunta a pessoa que fez e posto a solução aqui.
Mais uma vez, muito o brigado pela atenção vcs ajudaram muito.