Pesquisa Paginada Hibernate Sql Server 2000 muito lenta

Bom dia a todos,

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.

Valeu.

Alex,

se você executar a SQL que o hibernate gerou diretamente em um cliente SQLServer ele também demora todo esse tempo?

Sim.
Ao executar o sql gerado ele demora os mesmos 20 segundos.

Posta a SQL aí pra gnt dar uma analisada.

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

este é o dialeto usado:

  <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />

Para posta a Sql tive que editar o nome das tabelas, o chefe mandou. rss.
Mas acho que dá para entender.

Obrigado pela Compreensão.

E qual o SQL gerado para quando não tem paginação?
A mesma coisa, mas sem o top ‘n’ ?

Olá Alex,

eu nunca ouvi dizer que a instrução top causava lentidão na execução de consultas SQL.

Você percebeu que o problema não é do hibernate né? O problema é na SQL que está sendo executada.

Dê uma pesquisada na internet sobre problemas com o top e SQL Server.

Abraço.

Valeu Fábio.

È 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

Obrigado pela atenção.

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.

Espero ter ajudado.

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.

Obrigado pela Ajuda.

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.

Valeu.

Beleza Alex.

Parabéns por ter resolvido o problema.