Estou com um pequeno problema no trabalho, o ORM está gerando uma consulta muito estranha e preciso otimizar um pouco o resultado dele. Eu escrevi uma versão mais legível da consulta e o resultado é semelhante, mas o tempo de execução ainda é o mesmo.
Consulta Original
Explicar Detalhado
Esta é a consulta formatada atual, ela retorna o valor correto, mas leva cerca de 13 segundos para ser executada.
select count(*)
from reservation as r
JOIN companyclient as cc ON r.companyclientid = cc.companyclientid
JOIN reservationitem as ri ON r.reservationid = ri.reservationid
LEFT JOIN billingaccount as bi
ON (r.reservationid = bi.reservationid AND cc.companyclientid = bi.companyclientid AND
bi.propertyid = '84'
AND NOT bi.isdeleted
AND bi.groupkey = bi.billingaccountid
AND bi.billingaccounttypeid = '3'
AND bi.reservationid IS NOT NULL
AND bi.statusid = '1')
WHERE r.propertyid = '84'
AND NOT r.isdeleted
AND r.companyclientid is not null
AND ri.tenantid = '025aa64f-67fb-4c23-b975-2b0fc3f5d65a'
AND NOT ri.isdeleted
AND ri.reservationitemstatusid NOT IN (6, 3, 7, 8);
Esta é a versão que escrevi na tentativa de otimizar (de 13 segundos para 5), evitando as condições dentro da junção esquerda, mas o resultado é diferente da consulta original. A primeira consulta retorna 29490 e a segunda consulta retorna 29397.
select count(*)
from reservation as r
JOIN companyclient as cc ON r.companyclientid = cc.companyclientid
JOIN reservationitem as ri ON r.reservationid = ri.reservationid
LEFT JOIN billingaccount as bi
ON (r.reservationid = bi.reservationid AND cc.companyclientid = bi.companyclientid)
WHERE r.propertyid = '84'
AND NOT r.isdeleted
AND r.companyclientid is not null
AND ri.tenantid = '025aa64f-67fb-4c23-b975-2b0fc3f5d65a'
AND NOT ri.isdeleted
AND ri.reservationitemstatusid NOT IN (6, 3, 7, 8)
AND (bi is null or bi.propertyid = '84'
AND NOT bi.isdeleted
AND bi.groupkey = bi.billingaccountid
AND bi.billingaccounttypeid = '3'
AND bi.reservationid IS NOT NULL
AND bi.statusid = '1')
Minha dúvida é, como posso otimizar a primeira consulta, já tentei alguns métodos mas não tive muito sucesso. Entendo que a contagem é linear e seu tempo é baseado no tamanho do retorno da consulta, mas imagino que seja muito lento para uma consulta de 30 mil linhas.
Neste caso específico, preciso do total de itens para calcular o número de páginas na paginação de deslocamento limite.
Desde já agradeço a todos que tiveram a paciência de ler, aceito qualquer ajuda.
Tamanho das tabelas usadas no exemplo:
- reserva: 288549 linhas
- empresacliente: 50614 linhas
- item de reserva: 387820 linhas
- conta de cobrança: 772521 linhas