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.1: select * from B where B.FK in (5, 6, 7, 8) Ex.2: select * 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". |