Skip to content

Instantly share code, notes, and snippets.

@denoww
Created June 13, 2016 17:49
Show Gist options
  • Save denoww/725ce92733fadcff52a597f1ff8a0e61 to your computer and use it in GitHub Desktop.
Save denoww/725ce92733fadcff52a597f1ff8a0e61 to your computer and use it in GitHub Desktop.
Análise performance cobrança

Como ter performance ao listar cobranças com boletos e boleto_ocorrencias

Abordagem 1: resolver com uma querie complexa

def ultimo_boleto
    boletos.order('id desc').first # o order faz com que rode muitos selects
    # ou
    boletos.first # ou .last - me faz confiar cegamente na ordenação da querie complexa (qualquer erro é fatal)
end

def ultimo_boleto_ocorrencia
  ultimo_boleto.order('id desc').last  # idem
  ultimo_boleto.boleto_ocorrencias.last # idem
end
  • Contras
    • querie de dificil manutenção e qualquer erro é fatal
    • se o dev mexer no na coleção de boletos, a performance pode ser perdida
  • Prós:
    • Não precisa guardar campos a mais na tabela de cobranças e boletos

Abordagem 2: criar 1 campo a mais em cobranca e boleto

:cobranca belongs_to :ultimo_boleto
:boleto belongs_to :ultimo_boleto_ocorrencia

cobranca.ultimo_boleto
boleto.ultimo_boleto_ocorrencia
  • Prós:
    • Fácil conseguir performance com este comando Cobranca.includes(ultimo_boleto: ultimo_boleto_ocorrencia)
    • Baixa chance do ultimo boleto não ser o ultimo
  • Contras
    • Um campo a mais em cobranca (ultimo_boleto_id)
    • Um campo a mais em boleto (ultimo_boleto_ocorrencia_id)

Querie complexa da abordagem 1

A

SELECT *
FROM
  "financeiro_cobrancas"
LEFT OUTER JOIN 
  -- aqui ficaria o left outer join com unidade
LEFT OUTER JOIN 
  -- aqui ficaria o left outer join com pagador
LEFT OUTER JOIN
  "financeiro_boletos" ON financeiro_boletos.id = 
                       (SELECT
                          MAX(financeiro_boletos.id)
                        FROM
                          financeiro_boletos
                        WHERE
                          financeiro_boletos.cobranca_id = financeiro_cobrancas.id)
                       AND
                          "financeiro_boletos"."cobranca_id" = "financeiro_cobrancas"."id"
-- LEFT OUTER JOIN 
LEFT OUTER JOIN 
  "financeiro_boleto_ocorrencias" ON financeiro_boleto_ocorrencias.id = 
                                  (
                                    SELECT
                                      MAX(financeiro_boleto_ocorrencias.id)
                                    FROM
                                      financeiro_boleto_ocorrencias
                                    WHERE
                                      financeiro_boleto_ocorrencias.boleto_id = financeiro_boletos.id
                                  )
                                  AND 
                                    "financeiro_boleto_ocorrencias"."cobranca_id" = "financeiro_cobrancas"."id"
                                  AND
                                    "financeiro_boleto_ocorrencias"."remessa_id" IS NULL
                                  AND
                                    "financeiro_boleto_ocorrencias"."cancelada_em" IS NULL                                    
                                  AND
                                    "financeiro_boleto_ocorrencias"."boleto_id" = "financeiro_boletos"."id"
​
​
WHERE
  -- 
  --Aqui vem a busca do filtro avançado ou simples
  --

  -- se comentar estas duas linhas abaixo conseguimos cobranças sem boletos (left outer join)
  AND
    "financeiro_boletos"."id" IS NOT NULL
  AND
    "financeiro_boleto_ocorrencias"."id" IS NOT NULL

;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment