Eu tenho uma consulta em JPQL que quando é executada vejo no console do eclipse que várias outras consultas são disparadas junto com a principal.
List<Object[]> resultado = query.getResultList();
É exatamente nesta linha, que dispara o JPQL, assim que passa por ela começa a rodar vários outros JPQLs. Aparentemente são várias consultas para cada linha de resultado da principal.
Gostaria de saber o que é isso e se há uma maneira de evitar, pois está onerando demais a performance.
Para piorar a situação:
Estiva lendo nos sites e descobri que este problema é chamado de N+1.
Uma das soluções seria usar “FETCH”, mas estranho a consulta já está com esta clausula.
Outra solução é separar as consultas, mas as condições para trazer os dados envolvem todas as tabelas.
Não sei se tem como separá-las
Essas situações são raras. A maioria dos problemas com JPA é porque as pessoas não fazem a minima ideia do que estão fazendo e colocam EAGER em todo o lado e fazem queries a obter mais do que o que precisam.
De volta com esta query.
Não foi possível por em prática a Query Nativa por questões de padrão na empresa.
Estou, trabalhando com JPA numa versão do java 7 com banco de dados ORACLE
Esta é a query:
SELECT inte.*, desd.* FROM TAB_INTEGRA inte
INNER JOIN TAB_TOP top ON inte.ID_TOP = top.ID
INNER JOIN TAB_ORGANIZACAO org ON top.ID_ORG = org.ID_ORG
LEFT OUTER JOIN TAB_MIGRA migr ON top.ID_MIGR = migr.ID_MIGR,
TAB_DESDOBRAR desd
INNER JOIN TAB_ENQUADRAR enqua ON desd.ID_ENQUADRAR = enqua.ID_ENQUADRAR
WHERE 1 = 1
AND inte.ST_INTEGRA = 1
AND (org.DT_VIGENCIA IS NULL)
AND inte.ID_INTEGRA_TIPO = 0
AND ait.CD_ENQUADRAR = enqua.CD_ENQUADRAR
AND ait.CD_DESDOBRAR = desd.CD_DESDOBRAR
AND (trunc(top.DT_INFRACAO) BETWEEN enqua.DT_INI_ENQUADRAR
AND enqua.DT_FIM_ENQUADRAR)
AND (migr.ID_MIGR IS NULL
OR migr.ID_MIGR NOT IN (
SELECT migra.ID_MIGRACAO
FROM TAB_MIGRA migra
INNER JOIN TBPRE_ETAPA_MIGRA eta
ON migra.ID_MIGR = eta.ID_MIGR
WHERE eta.ETAPA_ANDAMENTO = 'S'
AND (eta.ID_ETAPA_MIGR_TIPO IN (1,2,3))
OR eta.ID_ETAPA_MIGR_TIPO = 7
AND eta.ST_ETAPA_MIGR <> 0
OR eta.ID_ETAPA_MIGR_TIPO = 7
AND eta.ST_ETAPA_MIGRA <> 0
)
)
AND org.ID_ORG IN (2981, 5818, 5824, 5826, 5880, 5896, 5989, 6025)
ORDER BY inte.DT_EVENTO, inte.ID_TOP
A query está com nomes de campos e tabelas fictícios.
Se constatarem algum erro no SQL é erro que cometi ao transporta-la para cá.
Ela funciona, demora mais funciona.
Eu fui retirando tabela por tabela para saber onde estaria a demora.
Cheguei nesta: TAB_INTEGRA
Ficou só: SELECT * FROM TAB_INTEGRA
Quando entra na linha Query.ResultSet fica um tempão pensando.
Quando starta, começa a fazer outros SELECTS * “que não tem nada haver com a TAB_INTEGRA”.
Eu já ví os relacionamentos da tabela, e não tem nenhuma relacão com as que falo acima *
Já foi verificado o banco para saber se há algo errado e nada foi constatado.
O select da TAB_INTEGRA no SQLDeveloper roda de boa.
Bom devo estar pedindo que se passe um quadrado num circulo. “Impossível”.
Mas a minha esperança é que possa ser algo do tipo que alguém fale: Quando acontece isso vc
precisa alterar tal código, quero dizer, algum problema pontual que se faz quando há um comportamento desses.
Se ninguém puder dar uma opinião porque realmente é impossível, não tem problema algum porque sei que é uma sinuca de bico.
Obrigado.
Aqui vai retornar as 267770 linhas. No SQL developer faz fetch de apenas algumas linhas e conforme fazes scroll, faz fetch de mais. No teu código se não tens qualquer lógica de paginação vai fazer fetch de todas as linhas de uma vez. Daí o “tempão” que fica pensando.
Bom dia pmlm,
Esta consulta, se entendi direito sua resposta, não será apresentada na tela como resultado.
esta consulta faz parte de um JOB que roda todo dia.
A cada linha de resposta, será feito um processamento alterando esta e outras tabelas.
O limite para processar é cerca 1600 a 2100 linhas.
O problema é que pelo fato de demorar muito, acontece o timeout.
Independentemente de apresentar na tela ou nao, estas a obter os dados da BD para a tua aplicação, certo? Tens de esperar que esses dados sejam consultados na BD e chegam a uma lista tua na aplicação.
Já verificaste se do lado da BD não há optimizações que possam ser feitas? Por exemplo criação de índices? Também vejo que a tua query inicial tem muitos “OR”. Normalmente para uma BD isso é sinónimo de maus planos de execução e longos tempos de processamento.