SQL - muito lento, otimizando

Top  Previous  Next

Estou testando um novo programa e quando eu executo a query abaixo, 

a query demora mais de 10 minutos para ser criada e no final dá erro 

de disco cheio pois meu HD só tem 300 MB de espaço livre e a query 

cria um arquivo .DB com mais de 300 MB. 

 

    SELECT T1.* FROM CadTitul T1, CadModal T3 

    WHERE  T1.'Status da Cota' = 'N' 

       AND T1.'Codigo Cliente-C. Receber' <> 0 

       AND T1.'Numero da Cota' BETWEEN :pCotaIni AND :pCotaFim 

       AND T1.'DV da Cota' LIKE :pSerie 

       AND T3.'Codigo da Modalidade' = T1.'Codigo da Modalidade' 

       AND EXISTS (SELECT T2.'Cliente - Fornecedor'COUNT(*) FROM MvPagRec T2 

                   WHERE T2.'Cliente - Fornecedor' = T1.'Codigo Cliente-C. Receber' 

                     AND T2.'Pagar - Receber' = 'R' 

                     AND T2.'Tipo Lancamento' = 'M' 

                     AND ((T2.'Valor da Baixa' = 0  AND T2.'Data do Vencimento' < :pDataBase) 

                       OR (T2.'Valor da Baixa' <> 0 AND T2.'Data da Baixa' > :pDataBase)) 

                   GROUP BY T2.'Cliente - Fornecedor' 

                   HAVING COUNT(*) = :pQuantid) 

    UNION 

    SELECT T1.* FROM CadDepen T1, CadModal T3 

    WHERE  T1.'Status da Cota' = 'N' 

       AND T1.'Codigo Cliente-C. Receber' <> 0 

       AND T1.'Numero da Cota' BETWEEN :pCotaIni AND :pCotaFim 

       AND T1.'DV da Cota' LIKE :pSerie 

       AND T3.'Codigo da Modalidade' = T1.'Codigo da Modalidade' 

       AND EXISTS (SELECT T2.'Cliente - Fornecedor'COUNT(*) FROM MvPagRec T2 

                   WHERE T2.'Cliente - Fornecedor' = T1.'Codigo Cliente-C. Receber' 

                     AND T2.'Pagar - Receber' = 'R' 

                     AND T2.'Tipo Lancamento' = 'M' 

                     AND ((T2.'Valor da Baixa' = 0  AND T2.'Data do Vencimento' < :pDataBase) 

                       OR (T2.'Valor da Baixa' <> 0 AND T2.'Data da Baixa' > :pDataBase)) 

                   GROUP BY T2.'Cliente - Fornecedor' 

                   HAVING COUNT(*) = :pQuantid) 

 

    Informações: 

    Tabelas : Paradox 5.0 for Windows 

    CadTitul : 3.370 registros 

    CadDepen : 8.586 registros 

    MvPagRec : 2.621 registros 

    CadModal : 10 registros 

      

 

    Dúvidas : 

    1) Como faço para a query executar mais rápido? 

    2) O arquivo .DB é deletado após a execução da query? 

    3) A tabela MVPagRec tende a crescer e minha dúvida é se a query ficará ainda mais lenta? 

 

--------------------------------------------- resposta ---------------------------------------

 

Seu problema reside no "exists". Essa é a operação mais lenta de todas as junções. 

Para CADA tupla da relação T1 será REFEITA a query do Exists

Se você possui 3300 registros em T1 e T2 possui 2600

você gerará um tráfego de 8 milhões e meio de registros!

 

    Isso sem contarmos o que vem depois do union! Por via de regra, pense no seguinte:

 

    Sejam as tabelas A e B, sendo que B possui FK (foreign key) de A, ou seja, há uma 

    relação 1-N de A para B

 

    1) Se você puder garantir que para toda tupla de B existe um correspondente de A 

       (digamos, com a FK not-null), use join simples. Esta é a junção mais veloz.

    

       Ex.: select * from A, B where B.FK = A.PK (primary key)

 

    2) Se você quiser garantir que FK em B pertence à um domínio específico, utilize IN.

 

        Ex.1select * from B where B.FK in (5678)

        Ex.2select * from B where B.FK in (select A.PK from A where A.CampoQualquer = 5)

 

        Obs.: o select a seguir é mais lento que o join simples porém surte o mesmo efeito:

 

               select * from B where B.FK in (select A.PK from A)

 

    3) Em último caso, APENAS se 1) e 2) não podem ser utilizados, use "exists".